# Credit Balance Source: https://docs.swarms.ai/api-reference/account-management/credit-balance https://api.swarms.world/openapi.json get /v1/account/credits Retrieves the current API credit balance for the authenticated user. # Get API Request Logs Source: https://docs.swarms.ai/api-reference/account-management/get-api-request-logs https://api.swarms.world/openapi.json get /v1/account/logs Retrieve all API request logs for all API keys associated with the authenticated user, excluding logs containing client IP information. # Get Premium Endpoints Source: https://docs.swarms.ai/api-reference/account-management/get-premium-endpoints https://api.swarms.world/openapi.json get /v1/account/premium-endpoints Retrieve all API endpoints that require a premium subscription. # Get User Metrics Summary Source: https://docs.swarms.ai/api-reference/account-management/get-user-metrics-summary https://api.swarms.world/openapi.json get /v1/account/metrics/summary Retrieve a summary of the authenticated user's core usage metrics, including unique agents used, lifetime completion calls, successful completions, and recent-window completion counts. # Execute Agent Completion Source: https://docs.swarms.ai/api-reference/agents/execute-agent-completion https://api.swarms.world/openapi.json post /v1/agent/completions Execute a single agent completion with the specified task. Supports both standard and streaming responses. # Execute Batch Agent Completions Source: https://docs.swarms.ai/api-reference/agents/execute-batch-agent-completions https://api.swarms.world/openapi.json post /v1/agent/batch/completions Execute multiple agent completions concurrently using optimized thread pool execution. This is a premium-only feature. # List Agent Configurations Source: https://docs.swarms.ai/api-reference/agents/list-agent-configurations https://api.swarms.world/openapi.json get /v1/agents/list Retrieve all unique agent configurations that the user has created or used, without task-specific details. Enables reuse of agent configurations across different tasks. # Generate Agent Configurations From a Task Source: https://docs.swarms.ai/api-reference/auto-agent-builder/generate-agent-configurations-from-a-task https://api.swarms.world/openapi.json post /v1/auto-agent-builder/completions Generate a roster of agent configurations for a task. A single builder agent designs the team and returns ready-to-post AgentSpec entries — the generated agents are not executed by this endpoint. # Execute Batched Grid Workflow Source: https://docs.swarms.ai/api-reference/batched-grid-workflow/execute-batched-grid-workflow https://api.swarms.world/openapi.json post /v1/batched-grid-workflow/completions Execute a batched grid workflow enabling parallel execution of multiple agents across multiple tasks in a single request. This is a premium-only feature. # API Root Source: https://docs.swarms.ai/api-reference/general/api-root https://api.swarms.world/openapi.json get / Root endpoint providing API welcome message and links to documentation and API key management. # Health Check Source: https://docs.swarms.ai/api-reference/general/health-check https://api.swarms.world/openapi.json get /health Health check endpoint to verify API service availability and operational status. # Execute Graph Workflow Source: https://docs.swarms.ai/api-reference/graph-workflow/execute-graph-workflow https://api.swarms.world/openapi.json post /v1/graph-workflow/completions Execute a graph workflow with directed agent nodes and edges. Enables complex multi-agent collaboration with parallel execution, automatic compilation, and comprehensive workflow orchestration. # Get API Request Logs (deprecated path) Source: https://docs.swarms.ai/api-reference/logging/get-api-request-logs-deprecated-path https://api.swarms.world/openapi.json get /v1/swarm/logs Deprecated alias for /v1/account/logs, kept for backwards compatibility. # Get User Metrics Summary (deprecated path) Source: https://docs.swarms.ai/api-reference/metrics/get-user-metrics-summary-deprecated-path https://api.swarms.world/openapi.json get /v1/metrics/summary Deprecated alias for /v1/account/metrics/summary, kept for backwards compatibility. # Get Available AI Models Source: https://docs.swarms.ai/api-reference/models/get-available-ai-models https://api.swarms.world/openapi.json get /v1/models/available Retrieve comprehensive information about all AI models available for use in agent and swarm configurations. # List Models (OpenAI-Compatible) Source: https://docs.swarms.ai/api-reference/models/list-models-openai-compatible https://api.swarms.world/openapi.json get /v1/models List all available models in the OpenAI-compatible format. Use with any OpenAI SDK or client that discovers models via GET /v1/models. # Chat Completions (OpenAI-compatible) Source: https://docs.swarms.ai/api-reference/openai-compatible/chat-completions-openai-compatible https://api.swarms.world/openapi.json post /v1/chat/completions OpenAI-compatible chat completions endpoint. Accepts the standard OpenAI request schema and returns the standard OpenAI response schema. Supports both streaming (SSE) and non-streaming modes. Works as a drop-in replacement with the OpenAI Python and TypeScript SDKs. # Get Comprehensive Pricing Details Source: https://docs.swarms.ai/api-reference/pricing/get-comprehensive-pricing-details https://api.swarms.world/openapi.json get /v1/usage/costs Retrieves comprehensive pricing details for all API features including usage costs, service costs, and special pricing features. # Get Rate Limits and Usage Source: https://docs.swarms.ai/api-reference/rate-limiting/get-rate-limits-and-usage https://api.swarms.world/openapi.json get /v1/rate/limits Retrieve current rate limit status and usage statistics for the authenticated user across multiple time windows. # Execute Reasoning Agent Completion Source: https://docs.swarms.ai/api-reference/reasoning-agents/execute-reasoning-agent-completion https://api.swarms.world/openapi.json post /v1/reasoning-agent/completions Execute a reasoning agent with advanced cognitive capabilities for complex problem-solving tasks. This is a premium-only feature. # Get Reasoning Agent Types Source: https://docs.swarms.ai/api-reference/reasoning-agents/get-reasoning-agent-types https://api.swarms.world/openapi.json get /v1/reasoning-agent/types Retrieve all available reasoning agent types. # Execute Batch Swarm Completions Source: https://docs.swarms.ai/api-reference/swarms/execute-batch-swarm-completions https://api.swarms.world/openapi.json post /v1/swarm/batch/completions Execute multiple swarm completions concurrently using optimized thread pool execution. This is a premium-only feature. # Execute Swarm Completion Source: https://docs.swarms.ai/api-reference/swarms/execute-swarm-completion https://api.swarms.world/openapi.json post /v1/swarm/completions Execute a swarm completion with the specified task. Supports both standard and streaming responses. # Get Available Swarm Types Source: https://docs.swarms.ai/api-reference/swarms/get-available-swarm-types https://api.swarms.world/openapi.json get /v1/swarms/available Retrieve all available swarm types supported by the Swarms API. # Get Available API Tools Source: https://docs.swarms.ai/api-reference/tool-management/get-available-api-tools https://api.swarms.world/openapi.json get /v1/tools/available Retrieve comprehensive information about all available tools and capabilities supported by the Swarms API. # Agent Completions Reference Source: https://docs.swarms.ai/docs/documentation/capabilities/agent Learn how to build individual agents and their capabilities with swarms The Agent Completions endpoint (`/v1/agent/completions`) enables you to execute individual AI agents with specific tasks, configurations, and capabilities. This endpoint provides a flexible way to run single agents with various models, tools, and configurations. ## Endpoint Information * **URL**: `/v1/agent/completions` * **Method**: `POST` * **Authentication**: Required (`x-api-key` header; `Authorization: Bearer ` is also accepted) * **Rate Limiting**: Subject to tier-based rate limits ## Request Schema ### AgentCompletion Object | Field | Type | Required | Description | | --------------- | ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `agent_config` | `AgentSpec` | Yes | The configuration of the agent to be completed | | `task` | `string` | No | The task to be completed by the agent | | `history` | `Union[Dict, List[Dict]]` | No | The history of the agent's previous tasks and responses. Can be either a dictionary or a list of message objects | | `img` | `string` | No | A base64 encoded image for the agent to process. Encode your image file to base64 and pass it here | | `imgs` | `List[string]` | No | A list of base64 encoded images for the agent to process. Encode your image files to base64 and pass them here | | `tools_enabled` | `List[string]` | No | Built-in tools for the agent. Supported values: `auto_search` (web search) and `web_scraper` (web scraping). Both may be listed together, in which case the agent receives both tools. Enabling a tool is billed once per request (a flat search or scrape fee), regardless of how many times the agent uses it | ### AgentSpec Object | Field | Type | Required | Default | Description | | ----------------------------- | ------------------------ | -------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `agent_name` | `string` | No | - | The unique name assigned to the agent, which identifies its role and functionality within the swarm | | `description` | `string` | No | - | A detailed explanation of the agent's purpose, capabilities, and any specific tasks it is designed to perform | | `system_prompt` | `string` | No | - | The initial instruction or context provided to the agent, guiding its behavior and responses during execution | | `marketplace_prompt_id` | `string` | No | - | The ID of a prompt from the Swarms marketplace to use as the system prompt. If provided, the prompt will be automatically retrieved from the marketplace | | `model_name` | `string` | No | `"claude-sonnet-5"` | The name of the AI model that the agent will utilize for processing tasks and generating outputs. For example: gpt-4o, gpt-4.1, openai/o3-mini | | `fallback_models` | `Optional[List[string]]` | No | `null` | Ordered list of models tried in sequence if the primary model fails; each is subject to the same free-tier restrictions as `model_name` | | `fallback_model_name` | `Optional[string]` | No | `null` | Single fallback model tried after any `fallback_models` | | `auto_generate_prompt` | `boolean` | No | `false` | A flag indicating whether the agent should automatically create prompts based on the task requirements | | `max_tokens` | `integer` | No | `16000` | The maximum number of tokens that the agent is allowed to generate in its responses, limiting output length. Values below 1 are rejected with a 422 validation error | | `temperature` | `float` | No | - | A parameter that controls the randomness of the agent's output; lower values result in more deterministic responses. If omitted, no temperature is sent to the model (the provider's own default applies) | | `role` | `string` | No | `"worker"` | The designated role of the agent within the swarm, which influences its behavior and interaction with other agents | | `max_loops` | `Union[int, string]` | No | `1` | Maximum number of iterations the agent can perform for its task. Accepts an integer of 1 or greater for a fixed count, or 'auto' to allow the system to determine the necessary number based on the task's complexity. Integer values below 1 are rejected with a 422 validation error | | `tools_list_dictionary` | `List[Dict]` | No | - | A dictionary of tools that the agent can use to complete its task | | `selected_tools` | `string \| List[string]` | No | All safe tools | Tools to enable for the autonomous looper when `max_loops="auto"`. Pass a list of tool names to restrict which tools the agent can use (e.g. `["think", "create_plan"]`). Available tools: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. Note: `run_bash` is not permitted for security reasons | | `mcp_url` | `string` | No | - | The URL of the MCP server that the agent can use to complete its task | | `streaming_on` | `boolean` | No | `false` | A flag indicating whether the agent should stream its output | | `llm_args` | `Dict` | No | - | Additional arguments to pass to the LLM such as top\_p, frequency\_penalty, presence\_penalty, etc. | | `dynamic_temperature_enabled` | `boolean` | No | `false` | A flag indicating whether the agent should dynamically adjust its temperature based on the task | | `mcp_config` | `MCPConnection` | No | - | The MCP connection to use for the agent | | `mcp_configs` | `MultipleMCPConnections` | No | - | The MCP connections to use for the agent. This is a list of MCP connections. Includes multiple MCP connections | | `tool_call_summary` | `boolean` | No | `true` | A parameter enabling an agent to summarize tool calls | | `reasoning_effort` | `string` | No | - (unset) | The effort to put into reasoning. Options: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `ultra`, `max`. For Claude 5-family models (`claude-sonnet-5`, `claude-opus-5`, `claude-fable-5`) reasoning parameters are currently ignored and the agent runs without extended thinking | | `thinking_tokens` | `integer` | No | - | The number of tokens to use for thinking | | `reasoning_enabled` | `boolean` | No | `false` | A parameter enabling an agent to use reasoning | | `publish_to_marketplace` | `boolean` | No | `false` | A flag indicating whether to publish this agent to the Swarms marketplace | | `use_cases` | `List[Dict[str, str]]` | No | - | A list of use case dictionaries with 'title' and 'description' keys. Required when publish\_to\_marketplace is True | | `tags` | `List[string]` | No | - | A list of searchable tags/keywords for the marketplace (e.g., \['finance', 'analysis']) | | `capabilities` | `List[string]` | No | - | A list of agent capabilities or features (e.g., \['trend-analysis', 'risk-assessment']) | | `category` | `string` | No | - | The marketplace category for the agent (e.g., 'research', 'content', 'coding', 'finance', 'healthcare', 'education', 'legal') | | `is_free` | `boolean` | No | `true` | A flag indicating whether the agent is free to use in the marketplace | | `price_usd` | `float` | No | - | The price in USD for using this agent in the marketplace (if not free) | | `handoffs` | `List[AgentSpec]` | No | - | A list of agent specifications that this agent can hand off tasks to. These agents will be created and passed to the agent's handoffs parameter | ## Response Schema ### AgentCompletionOutput Object | Field | Type | Description | | ------------- | --------- | ---------------------------------------- | | `job_id` | `string` | Unique identifier for the completion job | | `success` | `boolean` | Indicates successful execution | | `name` | `string` | Name of the executed agent | | `description` | `string` | Agent description | | `temperature` | `float` | Temperature setting used | | `outputs` | `any` | Generated output from the agent | | `usage` | `Dict` | Token usage and cost information | | `timestamp` | `string` | ISO timestamp of completion | ### Usage Information The response includes detailed usage metrics: ```json theme={null} { "usage": { "input_tokens": 150, "output_tokens": 300, "total_tokens": 450, "img_cost": 0.25, "total_cost": 0.256525 } } ``` ## Features and Capabilities ### 1. Multi-Model Support * **OpenAI Models**: gpt-4.1, gpt-4.1-mini, gpt-4o * **Anthropic Models**: claude-sonnet-4-20250514 * **Custom Models**: Any model supported by LiteLLM * **Vision Models**: Support for image analysis with gpt-4.1 and compatible models ### 2. Vision Capabilities * Single image analysis via `img` parameter * Multiple image analysis via `imgs` parameter * Automatic image token counting and cost calculation ### 3. Conversation History * Maintain context across multiple interactions * Support for both dictionary and list-based history formats * Automatic history formatting and token counting ### 4. Tool Integration * Enable built-in tools via `tools_enabled` parameter (`auto_search`, `web_scraper`) * MCP (Model Context Protocol) server integration * Custom tool dictionaries via `tools_list_dictionary` * Tool call summarization ### 5. Advanced Configuration * Dynamic temperature adjustment * Custom LLM arguments (top\_p, frequency\_penalty, presence\_penalty) * Streaming output support * Auto-prompt generation ## Examples ### Basic Agent Execution A simple example demonstrating how to execute a single agent with basic configuration. This example shows the minimum required fields to run an agent completion. ```python theme={null} import requests payload = { "agent_config": { "agent_name": "Research Analyst", "description": "Expert in analyzing and synthesizing research data", "system_prompt": "You are a Research Analyst with expertise in data analysis and synthesis.", "model_name": "gpt-4.1-mini", "max_tokens": 8192, "temperature": 0.7 }, "task": "Analyze the impact of artificial intelligence on healthcare" } response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Research Analyst", description: "Expert in analyzing and synthesizing research data", system_prompt: "You are a Research Analyst with expertise in data analysis and synthesis.", model_name: "gpt-4.1-mini", max_tokens: 8192, temperature: 0.7 }, task: "Analyze the impact of artificial intelligence on healthcare" }; const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify(payload) }); const result = await response.json(); ``` ```rust theme={null} use reqwest; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let payload = json!({ "agent_config": { "agent_name": "Research Analyst", "description": "Expert in analyzing and synthesizing research data", "system_prompt": "You are a Research Analyst with expertise in data analysis and synthesis.", "model_name": "gpt-4.1-mini", "max_tokens": 8192, "temperature": 0.7 }, "task": "Analyze the impact of artificial intelligence on healthcare" }); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", "your-api-key") .json(&payload) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{:?}", result); Ok(()) } ``` ### Agent with Conversation History This example demonstrates how to provide conversation history to maintain context across multiple interactions. The history can be provided as a dictionary or list format. ```python theme={null} payload = { "agent_config": { "agent_name": "Medical Assistant", "system_prompt": "You are a medical information assistant.", "model_name": "gpt-4.1-mini", "max_tokens": 4096 }, "task": "What are the symptoms of diabetes?", "history": { "message1": { "role": "user", "content": "Tell me about diabetes" }, "message2": { "role": "assistant", "content": "Diabetes is a chronic condition affecting blood sugar levels." } } } ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Medical Assistant", system_prompt: "You are a medical information assistant.", model_name: "gpt-4.1-mini", max_tokens: 4096 }, task: "What are the symptoms of diabetes?", history: { message1: { role: "user", content: "Tell me about diabetes" }, message2: { role: "assistant", content: "Diabetes is a chronic condition affecting blood sugar levels." } } }; ``` ```rust theme={null} use serde_json::json; let payload = json!({ "agent_config": { "agent_name": "Medical Assistant", "system_prompt": "You are a medical information assistant.", "model_name": "gpt-4.1-mini", "max_tokens": 4096 }, "task": "What are the symptoms of diabetes?", "history": { "message1": { "role": "user", "content": "Tell me about diabetes" }, "message2": { "role": "assistant", "content": "Diabetes is a chronic condition affecting blood sugar levels." } } }); ``` ### Agent with Search Capabilities Enable web search functionality for your agent by including `auto_search` in the `tools_enabled` parameter. This allows the agent to search the web for real-time information to complete tasks. Alternatively, pass `web_scraper` to let the agent scrape and format web pages. Both tools can be listed together, in which case the agent receives both and each is billed its own flat fee. ```python theme={null} payload = { "agent_config": { "agent_name": "Research Assistant", "description": "Research assistant with web search capabilities", "system_prompt": "You are a research assistant that can search the web.", "model_name": "gpt-4.1-mini", "max_tokens": 8192 }, "task": "Find the latest developments in quantum computing", "tools_enabled": ["auto_search"] } ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Research Assistant", description: "Research assistant with web search capabilities", system_prompt: "You are a research assistant that can search the web.", model_name: "gpt-4.1-mini", max_tokens: 8192 }, task: "Find the latest developments in quantum computing", tools_enabled: ["auto_search"] }; ``` ```rust theme={null} use serde_json::json; let payload = json!({ "agent_config": { "agent_name": "Research Assistant", "description": "Research assistant with web search capabilities", "system_prompt": "You are a research assistant that can search the web.", "model_name": "gpt-4.1-mini", "max_tokens": 8192 }, "task": "Find the latest developments in quantum computing", "tools_enabled": ["auto_search"] }); ``` ### Agent with MCP Integration Integrate Model Context Protocol (MCP) servers to extend your agent's capabilities. This example shows how to connect an agent to an MCP server for additional tools and resources. ```python theme={null} payload = { "agent_config": { "agent_name": "Data Analyst", "description": "Data analyst with database access", "system_prompt": "You are a data analyst with access to databases.", "model_name": "gpt-4.1-mini", "max_tokens": 8192, "mcp_url": "http://github.com/mcp" }, "task": "Query the customer database for recent orders" } ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Data Analyst", description: "Data analyst with database access", system_prompt: "You are a data analyst with access to databases.", model_name: "gpt-4.1-mini", max_tokens: 8192, mcp_url: "http://github.com/mcp" }, task: "Query the customer database for recent orders" }; ``` ```rust theme={null} use serde_json::json; let payload = json!({ "agent_config": { "agent_name": "Data Analyst", "description": "Data analyst with database access", "system_prompt": "You are a data analyst with access to databases.", "model_name": "gpt-4.1-mini", "max_tokens": 8192, "mcp_url": "http://github.com/mcp" }, "task": "Query the customer database for recent orders" }); ``` ### Agent with Custom LLM Arguments Customize advanced LLM parameters such as `top_p`, `frequency_penalty`, and `presence_penalty` to fine-tune the model's behavior. This is useful for controlling creativity, repetition, and topic diversity. ```python theme={null} payload = { "agent_config": { "agent_name": "Creative Writer", "description": "Creative writing specialist", "system_prompt": "You are a creative writing expert.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.9, "llm_args": { "top_p": 0.9, "frequency_penalty": 0.1, "presence_penalty": 0.1 } }, "task": "Write a creative story about time travel" } ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Creative Writer", description: "Creative writing specialist", system_prompt: "You are a creative writing expert.", model_name: "gpt-4.1", max_tokens: 2048, temperature: 0.9, llm_args: { top_p: 0.9, frequency_penalty: 0.1, presence_penalty: 0.1 } }, task: "Write a creative story about time travel" }; ``` ```rust theme={null} use serde_json::json; let payload = json!({ "agent_config": { "agent_name": "Creative Writer", "description": "Creative writing specialist", "system_prompt": "You are a creative writing expert.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.9, "llm_args": { "top_p": 0.9, "frequency_penalty": 0.1, "presence_penalty": 0.1 } }, "task": "Write a creative story about time travel" }); ``` ### Agent with Structured Outputs Use `tools_list_dictionary` to give the agent one or more OpenAI function-calling-style JSON schemas. The agent responds with structured tool calls that conform to your schema instead of free-form text — ideal for extraction, classification, and any workflow where downstream code parses the result. ```python theme={null} payload = { "agent_config": { "agent_name": "Invoice Extractor", "description": "Extracts structured invoice data from raw text", "system_prompt": "You extract invoice fields from documents. Always respond using the provided tool schema.", "model_name": "gpt-4o", "max_tokens": 1024, "temperature": 0.1, "tools_list_dictionary": [ { "type": "function", "function": { "name": "extract_invoice", "description": "Extract structured fields from an invoice", "parameters": { "type": "object", "properties": { "vendor": {"type": "string", "description": "Vendor or supplier name"}, "invoice_number": {"type": "string", "description": "Invoice identifier"}, "total_amount": {"type": "number", "description": "Total amount due in USD"}, "due_date": {"type": "string", "description": "Payment due date, ISO 8601"} }, "required": ["vendor", "invoice_number", "total_amount"] } } } ] }, "task": "Invoice ACME-2024-001 from Acme Corp: total $4,250.00, due 2026-08-01" } ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Invoice Extractor", description: "Extracts structured invoice data from raw text", system_prompt: "You extract invoice fields from documents. Always respond using the provided tool schema.", model_name: "gpt-4o", max_tokens: 1024, temperature: 0.1, tools_list_dictionary: [ { type: "function", function: { name: "extract_invoice", description: "Extract structured fields from an invoice", parameters: { type: "object", properties: { vendor: { type: "string", description: "Vendor or supplier name" }, invoice_number: { type: "string", description: "Invoice identifier" }, total_amount: { type: "number", description: "Total amount due in USD" }, due_date: { type: "string", description: "Payment due date, ISO 8601" } }, required: ["vendor", "invoice_number", "total_amount"] } } } ] }, task: "Invoice ACME-2024-001 from Acme Corp: total $4,250.00, due 2026-08-01" }; ``` ```rust theme={null} use serde_json::json; let payload = json!({ "agent_config": { "agent_name": "Invoice Extractor", "description": "Extracts structured invoice data from raw text", "system_prompt": "You extract invoice fields from documents. Always respond using the provided tool schema.", "model_name": "gpt-4o", "max_tokens": 1024, "temperature": 0.1, "tools_list_dictionary": [ { "type": "function", "function": { "name": "extract_invoice", "description": "Extract structured fields from an invoice", "parameters": { "type": "object", "properties": { "vendor": {"type": "string", "description": "Vendor or supplier name"}, "invoice_number": {"type": "string", "description": "Invoice identifier"}, "total_amount": {"type": "number", "description": "Total amount due in USD"}, "due_date": {"type": "string", "description": "Payment due date, ISO 8601"} }, "required": ["vendor", "invoice_number", "total_amount"] } } } ] }, "task": "Invoice ACME-2024-001 from Acme Corp: total $4,250.00, due 2026-08-01" }); ``` The agent's `outputs` content contains the structured tool call. The `function.arguments` field arrives as a JSON string, so parse it before use: ```python theme={null} import json result = response.json() tool_calls = result["outputs"][-1]["content"] invoice = json.loads(tool_calls[0]["function"]["arguments"]) print(invoice["vendor"], invoice["total_amount"]) ``` For schema-enforced plain-JSON responses without tool calls, you can alternatively pass `response_format` inside `llm_args`. See [Structured Outputs](/docs/examples/examples/structured-outputs) for a comparison of both approaches. ### Agent with Max Loops Control the number of execution iterations your agent performs using the `max_loops` parameter. This is useful for tasks that require multiple reasoning steps or iterative problem-solving. Set `max_loops` to a higher value (e.g., 3-5) for complex tasks that need multiple passes, or use `"auto"` for fully autonomous agents that decide when to stop. ```python theme={null} payload = { "agent_config": { "agent_name": "Problem Solver", "description": "Agent that performs iterative problem-solving", "system_prompt": "You are a problem-solving agent that breaks down complex tasks into steps and iteratively refines solutions.", "model_name": "gpt-4.1", "max_loops": 3, "max_tokens": 4096, "temperature": 0.7 }, "task": "Solve this multi-step problem: First, research the current state of renewable energy. Then, identify the top 3 challenges. Finally, propose solutions for each challenge." } response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` ```typescript theme={null} const payload = { agent_config: { agent_name: "Problem Solver", description: "Agent that performs iterative problem-solving", system_prompt: "You are a problem-solving agent that breaks down complex tasks into steps and iteratively refines solutions.", model_name: "gpt-4.1", max_loops: 3, max_tokens: 4096, temperature: 0.7 }, task: "Solve this multi-step problem: First, research the current state of renewable energy. Then, identify the top 3 challenges. Finally, propose solutions for each challenge." }; const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify(payload) }); const result = await response.json(); ``` ```rust theme={null} use reqwest; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let payload = json!({ "agent_config": { "agent_name": "Problem Solver", "description": "Agent that performs iterative problem-solving", "system_prompt": "You are a problem-solving agent that breaks down complex tasks into steps and iteratively refines solutions.", "model_name": "gpt-4.1", "max_loops": 3, "max_tokens": 4096, "temperature": 0.7 }, "task": "Solve this multi-step problem: First, research the current state of renewable energy. Then, identify the top 3 challenges. Finally, propose solutions for each challenge." }); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", "your-api-key") .json(&payload) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{:?}", result); Ok(()) } ``` ### Agent with Marketplace Prompt Use pre-built prompts from the Swarms marketplace by specifying the `marketplace_prompt_id`. When using a marketplace prompt, you don't need to provide `agent_name`, `description`, or `system_prompt` - the system will automatically retrieve and use the prompt configuration from the marketplace, including the agent's name, description, and system prompt. ```python theme={null} payload = { "agent_config": { "marketplace_prompt_id": "1191250b-9fb3-42e0-b0e9-25ec83260ab2", "model_name": "gpt-4.1-mini", "max_tokens": 8192 }, "task": "Your task here" } response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` ```typescript theme={null} const payload = { agent_config: { marketplace_prompt_id: "1191250b-9fb3-42e0-b0e9-25ec83260ab2", model_name: "gpt-4.1-mini", max_tokens: 8192 }, task: "Your task here" }; const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify(payload) }); const result = await response.json(); ``` ```rust theme={null} use reqwest; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let payload = json!({ "agent_config": { "marketplace_prompt_id": "1191250b-9fb3-42e0-b0e9-25ec83260ab2", "model_name": "gpt-4.1-mini", "max_tokens": 8192 }, "task": "Your task here" }); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", "your-api-key") .json(&payload) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{:?}", result); Ok(()) } ``` **Note**: When `marketplace_prompt_id` is provided, the system automatically fetches the agent's name, description, and system prompt from the marketplace. You can find marketplace prompts using the [Query Prompts API](/docs/marketplace/prompts-api#query-prompts). ### Agent with Image Analysis Enable vision capabilities by providing base64-encoded images to your agent. The agent can analyze single or multiple images and answer questions about visual content. Use the `img` parameter for a single image or `imgs` for multiple images. ```python theme={null} import requests import base64 # Encode an image from a file with open("path/to/image.jpg", "rb") as image_file: base64_image = base64.b64encode(image_file.read()).decode('utf-8') # Or encode from a URL # import requests as req # response = req.get("https://example.com/image.jpg") # base64_image = base64.b64encode(response.content).decode('utf-8') payload = { "agent_config": { "agent_name": "Image Analyzer", "description": "AI agent specialized in image analysis", "system_prompt": "You are an expert at analyzing and describing images in detail.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.5 }, "task": "Describe what you see in this image in detail", "img": base64_image } response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) result = response.json() print(result['outputs'][0]['content']) ``` ```typescript theme={null} import * as fs from 'fs'; // Encode an image from a file const imageBuffer = fs.readFileSync('path/to/image.jpg'); const base64Image = imageBuffer.toString('base64'); // Or encode from a URL // const imageResponse = await fetch('https://example.com/image.jpg'); // const arrayBuffer = await imageResponse.arrayBuffer(); // const base64Image = Buffer.from(arrayBuffer).toString('base64'); const payload = { agent_config: { agent_name: "Image Analyzer", description: "AI agent specialized in image analysis", system_prompt: "You are an expert at analyzing and describing images in detail.", model_name: "gpt-4.1", max_tokens: 2048, temperature: 0.5 }, task: "Describe what you see in this image in detail", img: base64Image }; const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify(payload) }); const result = await response.json(); console.log(result.outputs[0].content); ``` ```rust theme={null} use reqwest; use serde_json::json; use base64::{Engine as _, engine::general_purpose}; use std::fs; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); // Encode an image from a file let image_bytes = fs::read("path/to/image.jpg")?; let base64_image = general_purpose::STANDARD.encode(&image_bytes); let payload = json!({ "agent_config": { "agent_name": "Image Analyzer", "description": "AI agent specialized in image analysis", "system_prompt": "You are an expert at analyzing and describing images in detail.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.5 }, "task": "Describe what you see in this image in detail", "img": base64_image }); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", "your-api-key") .json(&payload) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{}", result["outputs"][0]["content"]); Ok(()) } ``` **Supported Models**: Only vision-capable models support image analysis: * `gpt-4.1`: Best for detailed visual analysis * `gpt-4.1-mini`: Cost-effective for basic vision tasks * `claude-sonnet-4-20250514`: High-quality vision understanding **Image Processing**: The API automatically calculates image token costs based on resolution. Larger images consume more tokens. See the [Vision Capabilities](/docs/examples/examples/vision-capabilities) guide for detailed information on image encoding and best practices. ## Batch Processing Process multiple agent completions simultaneously using the batch endpoint. This is useful for parallel processing of multiple tasks or running the same task with different configurations. **Premium Tier Required**: The `/v1/agent/batch/completions` endpoint is available only on Pro, Ultra, and Premium plans. [Upgrade your account](https://swarms.world/platform/account) to access batch processing capabilities. For processing multiple agents simultaneously, use the batch endpoint: **Endpoint**: `/v1/agent/batch/completions` **Request**: Array of `AgentCompletion` objects (max 50 per batch) ```python theme={null} payloads = [ { "agent_config": { "agent_name": "Analyst 1", "system_prompt": "You are a financial analyst.", "model_name": "gpt-4.1-mini" }, "task": "Analyze Q1 financial results" }, { "agent_config": { "agent_name": "Analyst 2", "system_prompt": "You are a market analyst.", "model_name": "gpt-4.1-mini" }, "task": "Evaluate market trends" } ] response = requests.post( "https://api.swarms.world/v1/agent/batch/completions", headers={"x-api-key": "your-api-key"}, json=payloads ) ``` ```typescript theme={null} const payloads = [ { agent_config: { agent_name: "Analyst 1", system_prompt: "You are a financial analyst.", model_name: "gpt-4.1-mini" }, task: "Analyze Q1 financial results" }, { agent_config: { agent_name: "Analyst 2", system_prompt: "You are a market analyst.", model_name: "gpt-4.1-mini" }, task: "Evaluate market trends" } ]; const response = await fetch('https://api.swarms.world/v1/agent/batch/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify(payloads) }); const result = await response.json(); ``` ```rust theme={null} use reqwest; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let payloads = json!([ { "agent_config": { "agent_name": "Analyst 1", "system_prompt": "You are a financial analyst.", "model_name": "gpt-4.1-mini" }, "task": "Analyze Q1 financial results" }, { "agent_config": { "agent_name": "Analyst 2", "system_prompt": "You are a market analyst.", "model_name": "gpt-4.1-mini" }, "task": "Evaluate market trends" } ]); let response = client .post("https://api.swarms.world/v1/agent/batch/completions") .header("x-api-key", "your-api-key") .json(&payloads) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{:?}", result); Ok(()) } ``` ## Error Handling The API returns appropriate HTTP status codes and error messages: * **400 Bad Request**: Invalid input parameters or validation failures * **401 Unauthorized**: Missing or invalid API key * **422 Unprocessable Entity**: Schema validation failures (e.g. a non-positive `max_loops` or `max_tokens`) * **429 Too Many Requests**: Rate limit exceeded * **500 Internal Server Error**: Server-side processing errors If an agent run produces no output for the given task, the API returns **HTTP 400** with a detail message like `Agent '' produced no output for this task. Nothing was charged...` instead of a success response. Callers should treat this as a retryable, client-visible error — nothing is billed for it. ## Rate Limits Rate limits are tier-based: * **Free Tier**: 100 requests/minute, 350 requests/hour, 50\*24 requests/day * **Premium Tier**: 2000 requests/minute, 10000 requests/hour, 100000 requests/day ## Cost Calculation For detailed pricing information, see the Pricing page. ## Best Practices 1. **Agent Naming**: Use descriptive, unique names for agents 2. **System Prompts**: Provide clear, specific instructions for consistent behavior 3. **Temperature Settings**: Use lower values (0.1-0.3) for analytical tasks, higher values (0.7-0.9) for creative tasks 4. **Token Limits**: Set appropriate max\_tokens based on expected response length 5. **History Management**: Keep conversation history concise to manage token costs 6. **Error Handling**: Implement proper error handling for production applications 7. **Rate Limiting**: Monitor usage and implement backoff strategies for rate limit handling ## Integration Examples ### Python SDK Usage Use the official Python SDK for a more convenient way to interact with the Swarms API. The SDK handles authentication, request formatting, and response parsing automatically. * pip3 install -U swarms-client * Put your `SWARMS_API_KEY` ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv import json load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) result = client.agent.run( agent_config={ "agent_name": "Bloodwork Diagnosis Expert", "description": "An expert doctor specializing in interpreting and diagnosing blood work results.", "system_prompt": ( "You are an expert medical doctor specializing in the interpretation and diagnosis of blood work. " "Your expertise includes analyzing laboratory results, identifying abnormal values, " "explaining their clinical significance, and recommending next diagnostic or treatment steps. " "Provide clear, evidence-based explanations and consider differential diagnoses based on blood test findings." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5, }, task=( "A patient presents with the following blood work results: " "Hemoglobin: 10.2 g/dL (low), WBC: 13,000 /µL (high), Platelets: 180,000 /µL (normal), " "ALT: 65 U/L (high), AST: 70 U/L (high). " "Please provide a detailed interpretation, possible diagnoses, and recommended next steps." ), ) print(json.dumps(result, indent=4)) ``` ### JavaScript/Node.js Integration Integrate the Swarms API into your JavaScript or Node.js applications using native `fetch` or any HTTP client library. This example demonstrates a basic implementation using the Fetch API. ```typescript theme={null} const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': 'your-api-key' }, body: JSON.stringify({ agent_config: { agent_name: "TypeScript Agent", system_prompt: "You are a helpful assistant.", model_name: "gpt-4.1-mini" }, task: "Explain TypeScript promises" }) }); const result = await response.json(); ``` ```rust theme={null} use reqwest; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let client = reqwest::Client::new(); let payload = json!({ "agent_config": { "agent_name": "Rust Agent", "system_prompt": "You are a helpful assistant.", "model_name": "gpt-4.1-mini" }, "task": "Explain Rust async/await" }); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", "your-api-key") .json(&payload) .send() .await?; let result: serde_json::Value = response.json().await?; println!("{:?}", result); Ok(()) } ``` ## Support and Resources * **API Keys**: [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) * **Technical Support**: [https://cal.com/swarms/swarms-technical-support](https://cal.com/swarms/swarms-technical-support) * **Community**: [Discord](https://discord.gg/EamjgSaEQf) ## Further Examples For end‑to‑end, copy‑pasteable examples built on top of this endpoint: * **Single Agent Completion (REST)** – minimal `requests` example using the new `agent_config` format:\ `/docs/examples/api_examples/agent_completion_single_agent` * **Autonomous Agents with `max_loops="auto"`** – tutorial for fully autonomous, tool‑using agents:\ `/docs/examples/api_examples/autonomous_agent_tutorial` # Fetch Previously Created Agents Source: https://docs.swarms.ai/docs/documentation/capabilities/agents_list Retrieve all agents you have created via the API The List Agents endpoint (`/v1/agents/list`) allows you to retrieve all agent configurations you have previously created through the Swarms API. This endpoint provides a comprehensive view of your agent inventory, including their names, descriptions, system prompts, model configurations, and other settings. When you create agents using the Swarms API (via the `/v1/agent/completions` endpoint or other agent creation methods), each agent configuration is stored in your account. The List Agents endpoint enables you to: * **View all your agents**: Retrieve a complete list of all agent configurations associated with your API key * **Manage your agent library**: Keep track of different agent configurations you've created for various use cases * **Reuse agent configurations**: Access previously created agent settings to reuse them in new tasks or workflows * **Audit and organize**: Review your agent inventory to understand what agents you have available and their configurations ## Endpoint Information * **URL**: `/v1/agents/list` * **Method**: `GET` * **Authentication**: Required (`x-api-key` header) * **Rate Limiting**: Subject to tier-based rate limits ## Response Format The endpoint returns a JSON object containing: * **`success`**: A boolean indicating whether the agent list was retrieved successfully * **`count`**: An integer representing the total number of unique agent configurations in your account * **`agents`**: An array of agent definition objects, each containing the complete configuration details of agents you've previously created, including: * Agent name and description * System prompts * Model configurations (model name, temperature, max\_tokens, etc.) * Tool configurations * MCP integrations * Other agent-specific settings * **`timestamp`**: An ISO 8601 UTC timestamp indicating when the list was generated ## Use Cases * **Agent Discovery**: Quickly see what agents you have available without needing to remember specific configuration details * **Configuration Reuse**: Retrieve agent configurations to reuse in new API calls or workflows * **Inventory Management**: Keep track of your agent library and identify agents that may need updates or cleanup * **Multi-Agent Workflows**: List available agents to select and combine them in complex multi-agent architectures * **Development and Testing**: Review agent configurations during development to ensure consistency across different environments ```python theme={null} import json import os from typing import Any, Dict import requests from dotenv import load_dotenv load_dotenv() BASE_URL = "https://api.swarms.world" HEADERS = { "x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json", } def list_agents() -> Dict[str, Any]: """Retrieve all unique agent configurations""" try: response = requests.get(f"{BASE_URL}/v1/agents/list", headers=HEADERS) assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}" response_data = response.json() print(json.dumps(response_data, indent=4)) count = response_data["count"] print(f"Number of agents: {count}") return response_data except Exception as e: print(str(e)) return {} if __name__ == "__main__": list_agents() ``` ```javascript theme={null} require('dotenv').config(); // const BASE_URL = "http://localhost:8080"; // const BASE_URL = "https://api.swarms.world"; const BASE_URL = "https://api.swarms.world"; const API_KEY = process.env.SWARMS_API_KEY; async function listAgents() { const resp = await fetch(`${BASE_URL}/v1/agents/list`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, }); if (!resp.ok) { console.error(`Error: ${resp.status} - ${await resp.text()}`); return; } const data = await resp.json(); console.log(JSON.stringify(data, null, 2)); console.log(`Number of agents: ${data.count}`); } listAgents().catch(console.error); ``` ```bash theme={null} #!/usr/bin/env bash # const BASE_URL="http://localhost:8080" # const BASE_URL="https://api.swarms.world" BASE_URL="https://api.swarms.world" curl -X GET "${BASE_URL}/v1/agents/list" \ -H "x-api-key: ${SWARMS_API_KEY}" \ -H "Content-Type: application/json" ``` Responses include a `count` of agents and an array of agent definitions you previously created. # MCP Integration Source: https://docs.swarms.ai/docs/documentation/capabilities/mcp_integration Integrate MCP Into your Agents This tutorial demonstrates how to integrate Model Context Protocol (MCP) servers with the Swarms API to create powerful quantitative agents that can fetch real-time data, perform statistical analysis, and provide financial insights. ## What is MCP? Model Context Protocol (MCP) is a standardized way for AI agents to interact with external data sources, tools, and services. By integrating MCP URLs with Swarms API, your quantitative agents can: * Fetch real-time financial data * Access historical market information * Perform complex statistical calculations * Integrate with external databases and APIs * Stream live market updates ## Key Components ### 1. MCP URL Configuration (`mcp_url`) The `mcp_url` field is all you need to connect your agent to an MCP server: ```json theme={null} { "mcp_url": "https://your-mcp-server.com/financial-data" } ``` The MCP server will automatically provide the available tools and capabilities to your agent. ### 2. Single MCP Connection (`mcp_config`) For more control over the connection (custom headers, an authorization token, transport, or a timeout), use `mcp_config` instead of `mcp_url`: ```json theme={null} { "mcp_config": { "type": "mcp", "url": "https://your-mcp-server.com/financial-data", "transport": "streamable_http", "authorization_token": "your-mcp-server-token", "headers": {"X-Custom-Header": "value"}, "timeout": 10 } } ``` ### 3. Multiple MCP Connections (`mcp_configs`) To connect a single agent to more than one MCP server at once, use `mcp_configs` with a list of connection objects (each using the same shape as `mcp_config`): ```json theme={null} { "mcp_configs": { "connections": [ {"type": "mcp", "url": "https://your-mcp-server.com/financial-data"}, {"type": "mcp", "url": "https://your-mcp-server.com/market-news"} ] } } ``` ## Complete Example: Quantitative Agent with MCP ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} def create_quant_agent_with_mcp(): """Create a quantitative agent that integrates with MCP server""" payload = { "agent_config": { "agent_name": "MCP-Enabled Quantitative Analyst", "description": "Quantitative analyst with MCP server integration for real-time data access", "system_prompt": ( "You are a Quantitative Data Analyst with direct access to MCP servers. " "Use the MCP tools to fetch real-time financial data, perform statistical analysis, " "and provide actionable insights. Always verify data quality and include source attribution." ), "model_name": "gpt-4.1", "role": "quantitative_analyst", "max_loops": 3, "max_tokens": 16384, "temperature": 0.3, "mcp_url": "https://your-mcp-server.com/financial-data", "streaming_on": False }, "task": ( "Connect to the MCP server and fetch the latest market data for AAPL, TSLA, and MSFT. " "Calculate volatility, Sharpe ratio, and correlation coefficients. " "Provide portfolio optimization recommendations based on the analysis." ) } return payload def run_mcp_agent(): """Execute the MCP-enabled quantitative agent""" payload = create_quant_agent_with_mcp() try: response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error: {e}") return None if __name__ == "__main__": result = run_mcp_agent() if result: print("MCP Agent executed successfully!") print(f"Job ID: {result.get('job_id', 'N/A')}") else: print("Failed to execute MCP agent") ``` ## Conclusion MCP integration with the Swarms API provides powerful capabilities for quantitative agents to access external data sources, perform complex analysis, and deliver real-time insights. By following the patterns and best practices outlined in this tutorial, you can create robust, scalable quantitative analysis systems that leverage the full power of MCP servers. For more information on MCP protocol specifications and advanced integration patterns, refer to the official MCP documentation and the Swarms API reference. # User Metrics Summary Source: https://docs.swarms.ai/docs/documentation/capabilities/metrics_summary Retrieve a summary of your core usage metrics in a single call The Metrics Summary endpoint (`/v1/account/metrics/summary`) returns an at-a-glance overview of your account's core usage metrics — how many unique agents you've used and completion-call counts derived from your request history — in a single response. This is the endpoint to power a usage dashboard: unique agents used, lifetime completion calls, and recent-window activity. ## Endpoint Information * **URL**: `/v1/account/metrics/summary` (the legacy path `/v1/metrics/summary` still works but is deprecated) * **Method**: `GET` * **Authentication**: Required (`x-api-key` header) * **Rate Limiting**: Subject to tier-based rate limits ## Response Format The endpoint returns a JSON object with the following fields: | Field | Type | Description | | ------------------------ | ------- | ------------------------------------------------------ | | `success` | boolean | Indicates the summary was retrieved successfully. | | `unique_agents` | integer | Number of unique agent configurations you have used. | | `total_completion_calls` | integer | Lifetime count of completion calls. | | `successful_completions` | integer | Lifetime count of completions with status `"success"`. | | `completions_last_24h` | integer | Completion calls in the last 24 hours. | | `completions_last_7d` | integer | Completion calls in the last 7 days. | | `timestamp` | string | ISO 8601 UTC timestamp when the summary was generated. | ### Example Response ```json theme={null} { "success": true, "unique_agents": 80, "total_completion_calls": 25583, "successful_completions": 13516, "completions_last_24h": 2, "completions_last_7d": 1151, "timestamp": "2026-07-06T11:54:17.401905+00:00" } ``` ## Use Cases * **Usage dashboards**: Populate headline tiles (executions, success rate, unique agents) from a single request. * **Activity monitoring**: Track 24-hour and 7-day completion volume to spot spikes or drop-offs. ```python theme={null} import json import os from typing import Any, Dict import requests from dotenv import load_dotenv load_dotenv() BASE_URL = "https://api.swarms.world" HEADERS = { "x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json", } def get_metrics_summary() -> Dict[str, Any]: """Retrieve a summary of your core usage metrics""" try: response = requests.get( f"{BASE_URL}/v1/account/metrics/summary", headers=HEADERS, ) assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}" data = response.json() print(json.dumps(data, indent=4)) print(f"Unique agents: {data['unique_agents']}") print(f"Total completion calls: {data['total_completion_calls']}") print(f"Successful completions: {data['successful_completions']}") print(f"Last 24h / 7d: {data['completions_last_24h']} / {data['completions_last_7d']}") return data except Exception as e: print(str(e)) return {} if __name__ == "__main__": get_metrics_summary() ``` ```javascript theme={null} require('dotenv').config(); const BASE_URL = "https://api.swarms.world"; const API_KEY = process.env.SWARMS_API_KEY; async function getMetricsSummary() { const url = `${BASE_URL}/v1/account/metrics/summary`; const resp = await fetch(url, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, }); if (!resp.ok) { console.error(`Error: ${resp.status} - ${await resp.text()}`); return; } const data = await resp.json(); console.log(JSON.stringify(data, null, 2)); console.log(`Unique agents: ${data.unique_agents}`); console.log(`Total completion calls: ${data.total_completion_calls}`); console.log(`Successful completions: ${data.successful_completions}`); console.log(`Last 24h / 7d: ${data.completions_last_24h} / ${data.completions_last_7d}`); } getMetricsSummary().catch(console.error); ``` ```bash theme={null} #!/usr/bin/env bash BASE_URL="https://api.swarms.world" curl -X GET "${BASE_URL}/v1/account/metrics/summary" \ -H "x-api-key: ${SWARMS_API_KEY}" \ -H "Content-Type: application/json" ``` To list your agent configurations, use [`/v1/agents/list`](/docs/documentation/capabilities/agents_list); for full request logs, use [`/v1/swarm/logs`](/docs/examples/examples/swarm-logs). # OpenAI-Compatible Endpoint Source: https://docs.swarms.ai/docs/documentation/capabilities/openai-compatible Complete API reference for the /v1/chat/completions endpoint — a drop-in replacement for the OpenAI API that routes through Swarms agent infrastructure. The Swarms API exposes an OpenAI-compatible `POST /v1/chat/completions` endpoint. If your application already uses the OpenAI SDK, you can switch to Swarms by changing two lines — the `base_url` and `api_key` — and everything else works unchanged. Under the hood, every request is routed through the full Swarms agent infrastructure: model routing, token counting, billing, and logging all apply exactly as they do for the native `/v1/agent/completions` endpoint. ## Endpoint Information * **URL**: `/v1/chat/completions` * **Method**: `POST` * **Authentication**: Required (`x-api-key` header or `Authorization: Bearer `) * **Rate Limiting**: Subject to tier-based rate limits *** ## Authentication Two authentication methods are supported. Both work on all Swarms API endpoints. | Method | Header | Example | | -------------- | ----------------------------- | --------------------------------- | | API key header | `x-api-key: ` | `x-api-key: sk-abc123` | | Bearer token | `Authorization: Bearer ` | `Authorization: Bearer sk-abc123` | The Bearer token method is what the OpenAI SDK sends by default, so it works out of the box. Get your API key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). *** ## Request Schema ### ChatCompletionRequest Object | Parameter | Type | Required | Default | Description | | ----------------------- | ------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model` | `string` | Yes | — | Model to use for completion (e.g. `gpt-4.1`, `claude-sonnet-4-20250514`, `gpt-4.1-mini`). Any model supported by the Swarms API is accepted | | `messages` | `List[ChatMessage]` | Yes | — | A list of messages comprising the conversation (see [ChatMessage Object](#chatmessage-object)) | | `temperature` | `float` | No | `0.5` | Sampling temperature (0.0 – 2.0). Lower values produce more deterministic output | | `max_tokens` | `integer` | No | `8192` | Maximum number of tokens to generate in the response | | `max_completion_tokens` | `integer` | No | — | Alternative to `max_tokens`. Takes precedence if both are set | | `stream` | `boolean` | No | `false` | If `true`, returns Server-Sent Events (SSE) in the OpenAI chunk format | | `top_p` | `float` | No | — | Nucleus sampling parameter. An alternative to temperature sampling | | `presence_penalty` | `float` | No | — | Penalize tokens based on whether they have appeared in the text so far | | `frequency_penalty` | `float` | No | — | Penalize tokens based on how frequently they appear in the text so far | | `n` | `integer` | No | `1` | Number of completions to generate. Only `1` is supported — requests with `n > 1` are rejected | | `user` | `string` | No | — | A unique identifier for the end-user, used for tracking | | `max_loops` | `integer` | No | `1` | *Swarms extension.* Maximum number of agent reasoning loops. `1` = single pass (default). Higher values let the agent iterate on its own output. Pass via `extra_body` in the OpenAI SDK | ### ChatMessage Object Each message in the `messages` array: | Field | Type | Required | Description | | --------- | ------------------------------- | -------- | ----------------------------------------------------------------------------------- | | `role` | `string` | Yes | One of `system`, `user`, or `assistant` | | `content` | `string` or `List[ContentPart]` | No | Text content, or an array of content parts for multimodal input. Defaults to `null` | | `name` | `string` | No | An optional name for the participant | #### ContentPart (Multimodal) When `content` is an array, each element is a content part: **Text part:** ```json theme={null} {"type": "text", "text": "Describe this image."} ``` **Image part:** ```json theme={null} {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}} ``` The `url` field accepts both HTTPS URLs and base64-encoded data URIs (`data:image/png;base64,...`). ### Validation Rules * At least one message with `role: "user"` is required * `n` must be `1` — multiple completions per request are not supported (send separate requests instead) * Requests with zero messages or only system messages are rejected ### Example Request Body ```json theme={null} { "model": "gpt-4.1", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Explain quantum computing in simple terms."} ], "temperature": 0.5, "max_tokens": 1024, "stream": false, "max_loops": 1 } ``` *** ## Response Schema ### ChatCompletionResponse Object (Non-Streaming) | Field | Type | Description | | --------- | ----------------- | -------------------------------------------------------------- | | `id` | `string` | Unique completion identifier, prefixed with `chatcmpl-` | | `object` | `string` | Always `"chat.completion"` | | `created` | `integer` | Unix timestamp of when the completion was generated | | `model` | `string` | The model that was used (echoes back the requested model name) | | `choices` | `List[Choice]` | Array containing the completion result (always one element) | | `usage` | `CompletionUsage` | Token usage counts for billing | ### Choice Object | Field | Type | Description | | --------------- | ------------- | ----------------------------------------------------------------- | | `index` | `integer` | Always `0` (single-choice responses) | | `message` | `ChatMessage` | The assistant's response with `role: "assistant"` | | `finish_reason` | `string` | Why the model stopped generating — `"stop"` for normal completion | ### CompletionUsage Object | Field | Type | Description | | ------------------- | --------- | -------------------------------------------------------------- | | `prompt_tokens` | `integer` | Number of tokens in the input (system prompt + history + task) | | `completion_tokens` | `integer` | Number of tokens in the generated response | | `total_tokens` | `integer` | Sum of `prompt_tokens` and `completion_tokens` | ### Example Response ```json theme={null} { "id": "chatcmpl-a1b2c3d4e5f6789012345678901", "object": "chat.completion", "created": 1711300000, "model": "gpt-4.1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "Quantum computing uses quantum bits (qubits) that can exist in multiple states simultaneously..." }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 42, "completion_tokens": 128, "total_tokens": 170 } } ``` *** ## Streaming Response Schema When `stream: true` is set, the response is returned as Server-Sent Events (SSE). Each event is a `data:` line containing a JSON chunk. ### StreamChunk Object | Field | Type | Description | | --------- | -------------------- | ---------------------------------------------------------- | | `id` | `string` | Same `chatcmpl-` ID shared across all chunks in the stream | | `object` | `string` | Always `"chat.completion.chunk"` | | `created` | `integer` | Unix timestamp (same across all chunks) | | `model` | `string` | The requested model name | | `choices` | `List[StreamChoice]` | Array with one element containing the delta | ### StreamChoice Object | Field | Type | Description | | --------------- | ------------------ | ---------------------------------------------------- | | `index` | `integer` | Always `0` | | `delta` | `object` | Incremental content — see stream sequence below | | `finish_reason` | `string` or `null` | `null` during streaming, `"stop"` on the final chunk | ### Stream Sequence | Order | `delta` | `finish_reason` | Purpose | | -------------- | ----------------------- | --------------- | ------------------------ | | First chunk | `{"role": "assistant"}` | `null` | Role declaration | | Content chunks | `{"content": "..."}` | `null` | Incremental text content | | Final chunk | `{}` | `"stop"` | Signals completion | | Terminator | `data: [DONE]` | — | SSE stream end marker | ### Example Stream ``` data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1711300000,"model":"gpt-4.1","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]} data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1711300000,"model":"gpt-4.1","choices":[{"index":0,"delta":{"content":"Quantum"},"finish_reason":null}]} data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1711300000,"model":"gpt-4.1","choices":[{"index":0,"delta":{"content":" computing"},"finish_reason":null}]} data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1711300000,"model":"gpt-4.1","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]} data: [DONE] ``` *** ## Error Response Schema Errors are returned in the standard OpenAI error format so the OpenAI SDK's built-in error classes work correctly: ### Error Object | Field | Type | Description | | --------------- | ------------------ | ----------------------------------- | | `error.message` | `string` | Human-readable error description | | `error.type` | `string` | Error category (see table below) | | `error.code` | `string` or `null` | Machine-readable error code | | `error.param` | `string` or `null` | The parameter that caused the error | ### Error Types | HTTP Status | `type` | When | | ----------- | ----------------------- | -------------------------------------------------------------- | | 400 | `invalid_request_error` | Malformed request, validation failure, missing required fields | | 401 | `authentication_error` | Missing or invalid API key | | 403 | `permission_error` | Insufficient permissions or subscription tier | | 429 | `rate_limit_error` | Rate limit exceeded | | 500 | `server_error` | Internal error during agent execution | Note: schema-validation failures on Swarms extension fields passed via `extra_body` (e.g. `max_loops: 0`) currently surface as a 500 `server_error` rather than a 400 `invalid_request_error`. Send `max_loops >= 1` to avoid this. ### Example Error Response ```json theme={null} { "error": { "message": "At least one message with role 'user' is required.", "type": "invalid_request_error", "code": "invalid_request", "param": null } } ``` *** ## Code Examples ### Non-Streaming Completion ```python theme={null} from openai import OpenAI client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the key trends in renewable energy?"}, ], max_tokens=1024, temperature=0.5, ) print(response.choices[0].message.content) print(f"Tokens used: {response.usage.total_tokens}") ``` ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: "your-swarms-api-key", baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a helpful assistant." }, { role: "user", content: "What are the key trends in renewable energy?" }, ], max_tokens: 1024, temperature: 0.5, }); console.log(response.choices[0].message.content); console.log(`Tokens used: ${response.usage?.total_tokens}`); ``` ```go theme={null} package main import ( "context" "fmt" "log" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey("your-swarms-api-key"), option.WithBaseURL("https://api.swarms.world/v1"), ) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("You are a helpful assistant."), openai.UserMessage("What are the key trends in renewable energy?"), }, MaxTokens: openai.Int(1024), Temperature: openai.Float(0.5), }, ) if err != nil { log.Fatal(err) } fmt.Println(response.Choices[0].Message.Content) fmt.Printf("Tokens used: %d\n", response.Usage.TotalTokens) } ``` ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; #[tokio::main] async fn main() -> Result<(), Box> { let config = OpenAIConfig::new() .with_api_key("your-swarms-api-key") .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestSystemMessageArgs::default() .content("You are a helpful assistant.") .build()? .into(), ChatCompletionRequestUserMessageArgs::default() .content("What are the key trends in renewable energy?") .build()? .into(), ]) .max_tokens(1024_u32) .temperature(0.5) .build()?; let response = client.chat().create(request).await?; if let Some(choice) = response.choices.first() { if let Some(content) = &choice.message.content { println!("{}", content); } } if let Some(usage) = &response.usage { println!("Tokens used: {}", usage.total_tokens); } Ok(()) } ``` ```bash theme={null} curl -X POST https://api.swarms.world/v1/chat/completions \ -H "Authorization: Bearer your-swarms-api-key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4.1", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the key trends in renewable energy?"} ], "max_tokens": 1024, "temperature": 0.5 }' ``` ### Streaming Completion ```python theme={null} from openai import OpenAI client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) stream = client.chat.completions.create( model="gpt-4.1", messages=[{"role": "user", "content": "Write a haiku about AI agents."}], stream=True, ) for chunk in stream: content = chunk.choices[0].delta.content if content: print(content, end="", flush=True) print() ``` ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: "your-swarms-api-key", baseURL: "https://api.swarms.world/v1", }); const stream = await client.chat.completions.create({ model: "gpt-4.1", messages: [{ role: "user", content: "Write a haiku about AI agents." }], stream: true, }); for await (const chunk of stream) { const content = chunk.choices[0]?.delta?.content; if (content) process.stdout.write(content); } console.log(); ``` ```go theme={null} package main import ( "context" "fmt" "log" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey("your-swarms-api-key"), option.WithBaseURL("https://api.swarms.world/v1"), ) stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Write a haiku about AI agents."), }, }, ) for stream.Next() { chunk := stream.Current() if len(chunk.Choices) > 0 { fmt.Print(chunk.Choices[0].Delta.Content) } } if err := stream.Err(); err != nil { log.Fatal(err) } fmt.Println() } ``` ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), Box> { let config = OpenAIConfig::new() .with_api_key("your-swarms-api-key") .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestUserMessageArgs::default() .content("Write a haiku about AI agents.") .build()? .into(), ]) .build()?; let mut stream = client.chat().create_stream(request).await?; while let Some(result) = stream.next().await { match result { Ok(response) => { for choice in &response.choices { if let Some(ref content) = choice.delta.content { print!("{}", content); } } } Err(e) => eprintln!("Error: {}", e), } } println!(); Ok(()) } ``` ```bash theme={null} curl -X POST https://api.swarms.world/v1/chat/completions \ -H "Authorization: Bearer your-swarms-api-key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4.1", "messages": [{"role": "user", "content": "Write a haiku about AI agents."}], "stream": true }' \ --no-buffer -N ``` ### Multi-Turn Conversation ```python theme={null} from openai import OpenAI client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a math tutor."}, {"role": "user", "content": "What is the derivative of x^2?"}, {"role": "assistant", "content": "The derivative of x^2 is 2x."}, {"role": "user", "content": "What about x^3?"}, ], ) print(response.choices[0].message.content) ``` ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: "your-swarms-api-key", baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a math tutor." }, { role: "user", content: "What is the derivative of x^2?" }, { role: "assistant", content: "The derivative of x^2 is 2x." }, { role: "user", content: "What about x^3?" }, ], }); console.log(response.choices[0].message.content); ``` ```go theme={null} package main import ( "context" "fmt" "log" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey("your-swarms-api-key"), option.WithBaseURL("https://api.swarms.world/v1"), ) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("You are a math tutor."), openai.UserMessage("What is the derivative of x^2?"), openai.AssistantMessage("The derivative of x^2 is 2x."), openai.UserMessage("What about x^3?"), }, }, ) if err != nil { log.Fatal(err) } fmt.Println(response.Choices[0].Message.Content) } ``` ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestAssistantMessageArgs, ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; #[tokio::main] async fn main() -> Result<(), Box> { let config = OpenAIConfig::new() .with_api_key("your-swarms-api-key") .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestSystemMessageArgs::default() .content("You are a math tutor.") .build()? .into(), ChatCompletionRequestUserMessageArgs::default() .content("What is the derivative of x^2?") .build()? .into(), ChatCompletionRequestAssistantMessageArgs::default() .content("The derivative of x^2 is 2x.") .build()? .into(), ChatCompletionRequestUserMessageArgs::default() .content("What about x^3?") .build()? .into(), ]) .build()?; let response = client.chat().create(request).await?; if let Some(choice) = response.choices.first() { if let Some(content) = &choice.message.content { println!("{}", content); } } Ok(()) } ``` ### Error Handling ```python theme={null} from openai import ( OpenAI, APIError, AuthenticationError, BadRequestError, PermissionDeniedError, RateLimitError, ) client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) try: response = client.chat.completions.create( model="gpt-4.1", messages=[{"role": "user", "content": "Hello"}], ) print(response.choices[0].message.content) except AuthenticationError: print("Missing API key (401)") except PermissionDeniedError: print("Invalid API key or insufficient permissions (403)") except BadRequestError as e: print(f"Validation error (400): {e.message}") except RateLimitError: print("Rate limited — back off and retry") except APIError as e: print(f"API error ({e.status_code}): {e.message}") ``` ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: "your-swarms-api-key", baseURL: "https://api.swarms.world/v1", }); try { const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [{ role: "user", content: "Hello" }], }); console.log(response.choices[0].message.content); } catch (error) { if (error instanceof OpenAI.AuthenticationError) { console.error("Missing API key (401)"); } else if (error instanceof OpenAI.PermissionDeniedError) { console.error("Invalid API key or insufficient permissions (403)"); } else if (error instanceof OpenAI.BadRequestError) { console.error(`Validation error (400): ${error.message}`); } else if (error instanceof OpenAI.RateLimitError) { console.error("Rate limited — back off and retry"); } else if (error instanceof OpenAI.APIError) { console.error(`API error (${error.status}): ${error.message}`); } } ``` ```go theme={null} package main import ( "context" "errors" "fmt" "log" "net/http" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey("your-swarms-api-key"), option.WithBaseURL("https://api.swarms.world/v1"), ) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("Hello"), }, }, ) if err != nil { var apiErr *openai.Error if errors.As(err, &apiErr) { switch apiErr.StatusCode { case http.StatusUnauthorized: log.Fatal("Missing API key (401)") case http.StatusForbidden: log.Fatal("Invalid API key or insufficient permissions (403)") case http.StatusBadRequest: log.Fatalf("Validation error (400): %s", apiErr.Message) case http.StatusTooManyRequests: log.Fatal("Rate limited — back off and retry") default: log.Fatalf("API error (%d): %s", apiErr.StatusCode, apiErr.Message) } } log.Fatal(err) } fmt.Println(response.Choices[0].Message.Content) } ``` ```rust theme={null} use async_openai::{ config::OpenAIConfig, error::OpenAIError, types::{ ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; #[tokio::main] async fn main() { let config = OpenAIConfig::new() .with_api_key("your-swarms-api-key") .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestUserMessageArgs::default() .content("Hello") .build() .unwrap() .into(), ]) .build() .unwrap(); match client.chat().create(request).await { Ok(response) => { if let Some(choice) = response.choices.first() { if let Some(content) = &choice.message.content { println!("{}", content); } } } Err(OpenAIError::ApiError(e)) => { eprintln!("API error: {}", e.message); } Err(e) => { eprintln!("Error: {}", e); } } } ``` *** ## Multi-Loop Reasoning By default the agent runs a single pass (`max_loops=1`). To let the agent iterate on its own output — useful for complex reasoning, self-correction, or multi-step tasks — pass `max_loops` via the OpenAI SDK's `extra_body` parameter: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a rigorous analyst. Think step by step, then review and refine your answer."}, {"role": "user", "content": "What are the second-order effects of raising the federal funds rate by 50 basis points?"}, ], max_tokens=2048, extra_body={"max_loops": 3}, ) print(response.choices[0].message.content) ``` ```typescript theme={null} import OpenAI from "openai"; const client = new OpenAI({ apiKey: "your-swarms-api-key", baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a rigorous analyst. Think step by step, then review and refine your answer." }, { role: "user", content: "What are the second-order effects of raising the federal funds rate by 50 basis points?" }, ], max_tokens: 2048, // @ts-expect-error — Swarms extension field max_loops: 3, }); console.log(response.choices[0].message.content); ``` ```bash theme={null} curl -X POST https://api.swarms.world/v1/chat/completions \ -H "Authorization: Bearer your-swarms-api-key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4.1", "messages": [ {"role": "system", "content": "You are a rigorous analyst. Think step by step, then review and refine your answer."}, {"role": "user", "content": "What are the second-order effects of raising the federal funds rate by 50 basis points?"} ], "max_tokens": 2048, "max_loops": 3 }' ``` `max_loops` is a Swarms extension field — it is not part of the OpenAI API spec. In the Python OpenAI SDK, use `extra_body={"max_loops": N}` to pass it. In cURL or raw HTTP, include it directly in the JSON body. *** ## How It Maps to Swarms Internals For users already familiar with the native Swarms API, here is how the OpenAI request fields map to `AgentCompletion` and `AgentSpec`: | OpenAI Field | Swarms Equivalent | Notes | | -------------------------------------- | -------------------------------------- | ----------------------------------------------------------------- | | `model` | `AgentSpec.model_name` | Passed through as-is | | `messages` (system) | `AgentSpec.system_prompt` | Defaults to "You are a helpful assistant." if absent | | `messages` (last user) | `AgentCompletion.task` | The actual prompt the agent runs on | | `messages` (prior turns) | `AgentCompletion.history` | User and assistant messages before the final user message | | `messages` (image\_url parts) | `AgentCompletion.img` / `imgs` | Extracted from multimodal content parts | | `temperature` | `AgentSpec.temperature` | Defaults to 0.5 | | `max_tokens` / `max_completion_tokens` | `AgentSpec.max_tokens` | `max_completion_tokens` takes precedence; defaults to 8192 | | `top_p` | `AgentSpec.llm_args.top_p` | Passed through to the underlying LLM | | `presence_penalty` | `AgentSpec.llm_args.presence_penalty` | Passed through to the underlying LLM | | `frequency_penalty` | `AgentSpec.llm_args.frequency_penalty` | Passed through to the underlying LLM | | `max_loops` | `AgentSpec.max_loops` | Defaults to 1. Higher values enable multi-loop reasoning | | `stream` | Route dispatch | `true` returns `StreamingResponse` with SSE; `false` returns JSON | The agent is created with `max_loops` set to the requested value (defaults to `1` for single-turn) and `streaming_on=False` (the agent itself runs to completion; streaming is simulated at the HTTP layer by chunking the result). *** ## Supported Models The `model` field accepts any model supported by the Swarms API. Common options: | Provider | Models | | --------- | ------------------------------------------------------------ | | OpenAI | `gpt-4.1`, `gpt-4.1-mini`, `gpt-4.1-nano`, `o3-mini` | | Anthropic | `claude-sonnet-4-20250514`, `claude-3-7-sonnet-latest` | | Groq | `groq/llama3-70b-8192`, `groq/deepseek-r1-distill-llama-70b` | For the full list, call `GET /v1/models` (standard OpenAI list format — works with `client.models.list()` in the OpenAI SDK) or `GET /v1/models/available` (Swarms format with a `count` field) with your API key. Both return the same catalog, filtered by your subscription tier: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="your-swarms-api-key", base_url="https://api.swarms.world/v1", ) models = client.models.list() print(f"{len(models.data)} models available") for model in models.data[:10]: print(f"{model.id} (owned_by: {model.owned_by})") ``` *** ## Differences from the OpenAI API | Behavior | OpenAI API | Swarms API | | ------------------------------- | ----------------------------- | ---------------------------------------------------------------------------------------- | | `n > 1` | Returns multiple choices | Rejected with error — send separate requests | | Tool calling / function calling | Supported | Not supported on this endpoint. Use `/v1/agent/completions` with `tools_list_dictionary` | | `logprobs` | Supported | Not supported | | Response format (`json_object`) | Supported | Not supported on this endpoint. Use `/v1/agent/completions` with structured output | | Streaming | True token-by-token streaming | Simulated — the agent runs to completion, then the result is delivered in chunks | | `max_loops` | Not applicable | Swarms extension — multi-loop agent reasoning (pass via `extra_body`) | *** ## Billing Usage is metered and billed identically to the native `/v1/agent/completions` endpoint: * **Input tokens** are counted from the combined system prompt, conversation history, and task * **Output tokens** are counted from the agent's response * **Credits are deducted** automatically after each completion * The `usage` field in the response shows the exact token counts Check your balance anytime with `GET /v1/account/credits`. # Premium Endpoints API Source: https://docs.swarms.ai/docs/documentation/capabilities/premium_endpoints_api Fetch the current list of premium-only API endpoints programmatically, with route, feature name, and description for each Retrieve every endpoint that requires a premium subscription from `/v1/account/premium-endpoints`. Each entry carries the route, a human-readable feature name, and a description of what the endpoint unlocks — so your application can gate its own UI without hardcoding a list that drifts out of date. This endpoint returns the *catalog* of premium routes. It does not tell you whether **your** account has premium access — a free-tier key can call it successfully and still receive `403` when it tries one of the listed routes. See [Premium Endpoints](/docs/documentation/resources/premium-endpoints) for the tier rules. ## Endpoint | Property | Value | | ------------------ | ------------------------------- | | **Method** | `GET` | | **Path** | `/v1/account/premium-endpoints` | | **Base URL** | `https://api.swarms.world` | | **Authentication** | `x-api-key` header (required) | | **Tier** | Available on all tiers | ## Quick Start ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def get_premium_endpoints() -> dict | None: """Fetch the catalog of premium-only endpoints.""" resp = requests.get( f"{BASE_URL}/v1/account/premium-endpoints", headers=headers, ) if resp.status_code == 200: return resp.json() print(f"Error: {resp.status_code} - {resp.text}") return None if __name__ == "__main__": data = get_premium_endpoints() if data: print(f"✅ {data['total']} premium endpoints") for endpoint in data["premium_endpoints"]: print(f" {endpoint['route']:45} {endpoint['name']}") print(f"\nUpgrade at: {data['upgrade_url']}") ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getPremiumEndpoints() { const response = await fetch(`${BASE_URL}/v1/account/premium-endpoints`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log(`✅ ${data.total} premium endpoints`); data.premium_endpoints.forEach(e => { console.log(` ${e.route.padEnd(45)} ${e.name}`); }); console.log(`\nUpgrade at: ${data.upgrade_url}`); return data; } getPremiumEndpoints(); ``` ```bash theme={null} curl -sS -X GET "https://api.swarms.world/v1/account/premium-endpoints" \ -H "x-api-key: $SWARMS_API_KEY" ``` Extract just the routes: ```bash theme={null} curl -sS "https://api.swarms.world/v1/account/premium-endpoints" \ -H "x-api-key: $SWARMS_API_KEY" \ | jq -r '.premium_endpoints[].route' ``` ## Response ```json theme={null} { "status": true, "timestamp": "2026-08-24T18:00:00.000000+00:00", "total": 5, "premium_endpoints": [ { "route": "/v1/graph-workflow/completions", "name": "Graph Workflow Completions", "description": "Execute graph workflows with directed agent nodes and edges." }, { "route": "/v1/agent/batch/completions", "name": "Batch Agent Completions", "description": "Process multiple agent tasks in parallel batches." }, { "route": "/v1/swarm/batch/completions", "name": "Batch Swarm Completions", "description": "Execute batch swarm completions with concurrent multi-agent execution." }, { "route": "/v1/reasoning-agent/completions", "name": "Reasoning Agent Completions", "description": "Execute advanced reasoning agent tasks using specialized reasoning architectures." }, { "route": "/v1/batched-grid-workflow/completions", "name": "Batched Grid Workflow", "description": "Execute multiple tasks across multiple agents in a grid pattern." } ], "upgrade_url": "https://cloud.swarms.world/settings" } ``` ### Response Schema | Field | Type | Description | | ------------------- | ---------------- | --------------------------------------------------------------------- | | `status` | `boolean` | Whether fetching the premium endpoints succeeded. Defaults to `true`. | | `timestamp` | `string \| null` | ISO-formatted timestamp of when the response was generated. | | `total` | `integer` | Number of premium endpoints. | | `premium_endpoints` | `array` | One `PremiumEndpointInfo` object per premium-only route. | | `upgrade_url` | `string` | Where to upgrade to a premium subscription. | ### PremiumEndpointInfo | Field | Type | Description | | ------------- | -------- | -------------------------------------------------------- | | `route` | `string` | The API route path that requires a premium subscription. | | `name` | `string` | Human-readable feature name for the endpoint. | | `description` | `string` | What the endpoint allows a premium subscriber to do. | ### Status Codes | Code | Meaning | | ----- | ---------------------------------------------------------- | | `200` | Catalog returned successfully | | `401` | Missing or invalid `x-api-key` | | `422` | Validation error — the `x-api-key` header was not supplied | ## Gating Your Own UI Rather than shipping a hardcoded list, fetch the catalog at startup and use it to decide what to show: ```python theme={null} PREMIUM_ROUTES = { e["route"] for e in get_premium_endpoints()["premium_endpoints"] } def is_premium(route: str) -> bool: """True when a route needs a premium subscription.""" return route in PREMIUM_ROUTES # Disable the batch button for free-tier users instead of letting the call 403 if is_premium("/v1/swarm/batch/completions"): show_upgrade_prompt() ``` The catalog changes as endpoints are added or re-tiered. Cache it for minutes, not for the lifetime of a deployment, and never bake the routes into a released binary. ## Related Resources Tier rules and the 403 error shape Plan comparison and model gating Premium endpoints also require credits above \$1.00 Tier-based request limits # Reasoning Agent Completions Source: https://docs.swarms.ai/docs/documentation/capabilities/reasoning_agent Execute reasoning agents with specialized cognitive architectures — self-consistency, reasoning duo, iterative reflective expansion, and more — via /v1/reasoning-agent/completions The Reasoning Agent Completions endpoint (`/v1/reasoning-agent/completions`) runs a single task through a specialized reasoning architecture rather than a plain agent loop. Instead of one model call producing one answer, a reasoning agent decomposes, samples, critiques, or debates its way to a result — trading cost and latency for reliability on problems where a single pass is often wrong. **Premium tier required.** This endpoint is restricted to Pro, Ultra, and Premium subscribers. Free-tier keys receive a `403` with upgrade instructions. See [Premium Endpoints](/docs/documentation/resources/premium-endpoints). ## Endpoint | Property | Value | | ------------------ | --------------------------------- | | **Method** | `POST` | | **Path** | `/v1/reasoning-agent/completions` | | **Base URL** | `https://api.swarms.world` | | **Authentication** | `x-api-key` header (required) | | **Tier** | Pro, Ultra, Premium | ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A["Reasoning architecture"] A --> S1["Pass 1"] A --> S2["Pass 2"] A --> S3["Pass 3"] S1 --> R["Reconciled answer"] S2 --> R S3 --> R ``` The exact internals depend on `swarm_type` — some architectures sample independently and reconcile, others critique and revise in sequence. What they share is that one request produces multiple internal reasoning passes before returning. ## ReasoningAgentSpec The request body is a single `ReasoningAgentSpec` object. | Parameter | Type | Required | Default | Description | | --------------------- | --------- | -------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `task` | `string` | Yes | `null` | The task to be completed by the reasoning agent | | `agent_name` | `string` | No | `"reasoning-agent"` | Unique name assigned to the reasoning agent | | `description` | `string` | No | `"A reasoning agent that can answer questions and help with tasks."` | Explanation of the agent's purpose and capabilities | | `model_name` | `string` | No | `"claude-sonnet-4-20250514"` | The AI model backing the reasoning agent | | `system_prompt` | `string` | No | `null` | Initial instruction or context provided to the agent | | `max_loops` | `integer` | No | `1` | Maximum times the agent repeats its task. Between 1 and 50 | | `swarm_type` | `string` | No | `"reasoning_duo"` | The reasoning architecture to use — see [Reasoning Types](#reasoning-types) | | `num_samples` | `integer` | No | `1` | Number of samples to generate. Drives the vote count for consensus architectures | | `output_type` | `string` | No | `"dict-all-except-first"` | Output format — see [Output Types](#output-types) | | `num_knowledge_items` | `integer` | No | `null` | Number of knowledge items to use | | `memory_capacity` | `integer` | No | `null` | Memory capacity for the reasoning agent | ### Reasoning Types `swarm_type` accepts the following values: | Value | Description | | ------------------- | -------------------------------------------------------- | | `reasoning-duo` | Two agents in dialogue — one reasons, one critiques | | `reasoning-agent` | Single agent with extended reasoning | | `self-consistency` | Samples multiple independent answers and reconciles them | | `consistency-agent` | Consistency-checking variant | | `ire` | Iterative reflective expansion | | `ire-agent` | IRE agent variant | | `ReflexionAgent` | Reflects on prior attempts and revises | | `GKPAgent` | Generated-knowledge prompting | | `AgentJudge` | Judges and scores candidate answers | The default is `reasoning_duo` (underscore), while the enum lists `reasoning-duo` (hyphen). Pass one of the enumerated values explicitly rather than relying on the default. Call [`GET /v1/reasoning-agent/types`](/docs/examples/examples/reasoning-agent-types) for the live list. ### Output Types `output_type` controls the shape of `outputs`: `list`, `dict`, `dictionary`, `string`, `str`, `final`, `last`, `json`, `all`, `yaml`, `xml`, `dict-all-except-first`, `str-all-except-first`, `basemodel`, `dict-final`, `list-final`. Use `final` or `last` when you want only the answer. Use the default `dict-all-except-first` when you want the reasoning trace alongside it. ## Quick Start ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } payload = { "agent_name": "Valuation Reasoner", "description": "Works through multi-step valuation problems", "model_name": "claude-sonnet-5", "swarm_type": "self-consistency", "num_samples": 3, "max_loops": 1, "output_type": "dict-all-except-first", "task": ( "A SaaS company has $12M ARR growing 40% YoY, 80% gross margin, " "and burns $500K/month. At a 6x forward revenue multiple, what is " "the implied valuation, and how many months of runway remain on a " "$20M cash balance? Show your reasoning." ), } def run_reasoning_agent() -> dict | None: resp = requests.post( f"{BASE_URL}/v1/reasoning-agent/completions", headers=headers, json=payload, timeout=600, ) if resp.status_code == 200: return resp.json() print(f"Error: {resp.status_code} - {resp.text}") return None if __name__ == "__main__": data = run_reasoning_agent() if data: print(f"✅ Job {data['job_id']} ({data['agent_type']})") print(json.dumps(data["outputs"], indent=2)) print(f"Tokens: {data['usage'].get('total_tokens')}") ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const payload = { agent_name: "Valuation Reasoner", description: "Works through multi-step valuation problems", model_name: "claude-sonnet-5", swarm_type: "self-consistency", num_samples: 3, max_loops: 1, output_type: "dict-all-except-first", task: "A SaaS company has $12M ARR growing 40% YoY, 80% gross margin, and burns $500K/month. At a 6x forward revenue multiple, what is the implied valuation, and how many months of runway remain on a $20M cash balance? Show your reasoning." }; async function runReasoningAgent() { const response = await fetch(`${BASE_URL}/v1/reasoning-agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); } const data = await response.json(); console.log(`✅ Job ${data.job_id} (${data.agent_type})`); console.log(JSON.stringify(data.outputs, null, 2)); return data; } runReasoningAgent(); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/reasoning-agent/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_name": "Valuation Reasoner", "description": "Works through multi-step valuation problems", "model_name": "claude-sonnet-5", "swarm_type": "self-consistency", "num_samples": 3, "max_loops": 1, "output_type": "dict-all-except-first", "task": "A SaaS company has $12M ARR growing 40% YoY, 80% gross margin, and burns $500K/month. At a 6x forward revenue multiple, what is the implied valuation, and how many months of runway remain on a $20M cash balance? Show your reasoning." }' ``` ## Response ```json theme={null} { "job_id": "reasoning-agent-7f3a2b1c", "status": "success", "outputs": [ { "role": "Valuation Reasoner", "content": "Implied valuation: $12M ARR x 1.40 = $16.8M forward revenue, x 6 = $100.8M. Runway: $20M / $0.5M per month = 40 months." } ], "timestamp": "2026-08-24T18:00:00.000000+00:00", "agent_name": "Valuation Reasoner", "agent_type": "self-consistency", "agent_id": "agent-4d9e1f22", "usage": { "input_tokens": 180, "output_tokens": 940, "total_tokens": 1120 } } ``` ### Response Schema | Field | Type | Description | | ------------ | -------- | -------------------------------------------------------------------------- | | `job_id` | `string` | Unique identifier for the reasoning agent run | | `status` | `string` | Status of the run. Defaults to `"success"` | | `outputs` | `any` | The generated output. **Shape varies by reasoning type** and `output_type` | | `timestamp` | `string` | ISO-formatted timestamp of when the run executed | | `agent_name` | `string` | Name of the agent | | `agent_type` | `string` | The reasoning architecture that ran (the `swarm_type`) | | `agent_id` | `string` | Unique identifier for the agent instance | | `usage` | `object` | Token counts — integer values keyed by name | `outputs` is deliberately untyped in the schema: a `self-consistency` run and a `reasoning-duo` run return different structures, and `output_type` changes it again. Do not assume a fixed shape — branch on `agent_type`, or pin `output_type` to `final` when you only need the answer string. ### Status Codes | Code | Meaning | | ----- | --------------------------------------------------------------- | | `200` | Completion returned successfully | | `401` | Missing or invalid `x-api-key` | | `402` | Credit balance below \$1.00 | | `403` | Free tier — premium subscription required | | `422` | Validation error — malformed body or missing `x-api-key` header | | `429` | Rate limit exceeded | ## When to Use a Reasoning Agent Reasoning agents cost more than a plain agent call — multiple internal passes means multiple sets of billed tokens. They earn that cost on problems where a single pass is unreliable: | Use it for | Use a plain agent for | | -------------------------------------------------------------------------------- | --------------------------------------------------- | | Multi-step quantitative problems where an arithmetic slip invalidates the answer | Summarization, extraction, rewriting | | Questions with a verifiable right answer worth double-checking | Open-ended generation with no single correct output | | High-stakes classification where a wrong call is expensive | High-volume, low-stakes classification | | Problems where you want the reasoning trace as an artifact | Cases where only the final text matters | Raise `num_samples` to increase consensus strength on `self-consistency`; raise `max_loops` to give reflective architectures more revision rounds. Both multiply cost roughly linearly. ## Related Resources Fetch the live list of reasoning architectures Worked example on a hard analytical problem The standard single-agent endpoint Tier requirements and the 403 error shape # Sub-Agent Delegation Source: https://docs.swarms.ai/docs/documentation/capabilities/sub_agents Enable agents to dynamically create and delegate tasks to specialized sub-agents at runtime Sub-agent delegation allows a single coordinator agent to **dynamically spawn specialized child agents** and distribute tasks across them for parallel execution. The coordinator analyzes the main task, creates purpose-built sub-agents, assigns work, and aggregates results — all autonomously. This capability is built on top of the [autonomous agent mode](/docs/examples/api_examples/autonomous_agent_tutorial) (`max_loops="auto"`) and uses two internal tools: `create_sub_agent` and `assign_task`. ## How It Works ```mermaid theme={null} flowchart TD A[Task Received by Coordinator] --> B[Planning Phase] B --> C[Create Sub-Agents] C --> D[Assign Tasks to Sub-Agents] D --> E1[Sub-Agent 1 Executes] D --> E2[Sub-Agent 2 Executes] D --> E3[Sub-Agent N Executes] E1 --> F[Results Aggregated] E2 --> F E3 --> F F --> G[Coordinator Compiles Final Output] ``` 1. **Planning** — The coordinator agent analyzes the task and determines what specialized sub-agents are needed 2. **Creation** — The coordinator calls `create_sub_agent` to spawn agents with specific names, descriptions, and system prompts 3. **Delegation** — The coordinator calls `assign_task` to distribute work to sub-agents, which execute concurrently 4. **Aggregation** — Results from all sub-agents are collected and the coordinator synthesizes a final response ## Enabling Sub-Agents Sub-agent delegation requires two configuration settings on your agent: | Parameter | Value | Purpose | | ---------------- | ----------------------------------------------------------- | -------------------------------------------------- | | `max_loops` | `"auto"` | Enables the autonomous agent loop with tool access | | `selected_tools` | `"all"` or include `"create_sub_agent"` and `"assign_task"` | Grants the agent access to sub-agent tools | When `max_loops="auto"` is set without specifying `selected_tools`, all safe default tools are enabled including sub-agent tools. ## Available Tools ### `create_sub_agent` Creates and caches one or more specialized sub-agents on the coordinator. | Parameter | Type | Required | Description | | ---------------------------- | -------- | -------- | ----------------------------------------------------------------------------- | | `agents` | `array` | Yes | List of sub-agent specifications | | `agents[].agent_name` | `string` | Yes | Unique identifier for the sub-agent | | `agents[].agent_description` | `string` | Yes | Role and capabilities description | | `agents[].system_prompt` | `string` | No | Custom instructions for the sub-agent. Defaults to a description-based prompt | Each sub-agent receives a unique ID in the format `sub-agent-{uuid}` (e.g., `sub-agent-a1b2c3d4`) and is stored in the coordinator's internal cache for reuse. ### `assign_task` Distributes tasks to previously created sub-agents for concurrent execution. | Parameter | Type | Required | Description | | ------------------------ | --------- | -------- | -------------------------------------------------------------------------------- | | `assignments` | `array` | Yes | List of task assignments | | `assignments[].agent_id` | `string` | Yes | Target sub-agent ID from creation step | | `assignments[].task` | `string` | Yes | Task description to delegate | | `assignments[].task_id` | `string` | No | Assignment identifier. Defaults to `task-{index}` | | `wait_for_completion` | `boolean` | No | If `true` (default), waits for all results. If `false`, fire-and-forget dispatch | Sub-agent tasks run concurrently using asynchronous execution, so multiple sub-agents work in parallel. ## API Usage Sub-agents are used through the standard `/v1/agent/completions` endpoint. The coordinator agent autonomously invokes the sub-agent tools during its execution loop. ### Basic Example ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Research-Coordinator", "description": "Coordinates parallel research across multiple domains", "system_prompt": ( "You are a research coordinator. Break down complex research tasks " "by creating specialized sub-agents for each domain, then delegate " "research tasks to them and compile a comprehensive report from their findings." ), "model_name": "gpt-4.1", "max_loops": "auto", "max_tokens": 8192, "temperature": 0.3 }, "task": ( "Research the current state of quantum computing. Cover three areas in parallel: " "1) Hardware advances (superconducting qubits, trapped ions, photonic systems), " "2) Software and algorithms (error correction, quantum advantage demonstrations), " "3) Commercial applications (finance, pharma, logistics). " "Create a sub-agent for each area, assign research tasks, and compile a summary." ) } response = requests.post( f"{API_BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=300 ) result = response.json() print(result) ``` ```python theme={null} import os from dotenv import load_dotenv import json from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=300, ) result = client.agent.run( agent_config={ "agent_name": "Research-Coordinator", "description": "Coordinates parallel research across multiple domains", "system_prompt": ( "You are a research coordinator. Break down complex research tasks " "by creating specialized sub-agents for each domain, then delegate " "research tasks to them and compile a comprehensive report from their findings." ), "model_name": "gpt-4.1", "max_loops": "auto", "max_tokens": 8192, "temperature": 0.3, }, task=( "Research the current state of quantum computing. Cover three areas in parallel: " "1) Hardware advances (superconducting qubits, trapped ions, photonic systems), " "2) Software and algorithms (error correction, quantum advantage demonstrations), " "3) Commercial applications (finance, pharma, logistics). " "Create a sub-agent for each area, assign research tasks, and compile a summary." ), ) print(json.dumps(result, indent=4)) ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const payload = { agent_config: { agent_name: "Research-Coordinator", description: "Coordinates parallel research across multiple domains", system_prompt: "You are a research coordinator. Break down complex research tasks " + "by creating specialized sub-agents for each domain, then delegate " + "research tasks to them and compile a comprehensive report from their findings.", model_name: "gpt-4.1", max_loops: "auto", max_tokens: 8192, temperature: 0.3, }, task: "Research the current state of quantum computing. Cover three areas in parallel: " + "1) Hardware advances (superconducting qubits, trapped ions, photonic systems), " + "2) Software and algorithms (error correction, quantum advantage demonstrations), " + "3) Commercial applications (finance, pharma, logistics). " + "Create a sub-agent for each area, assign research tasks, and compile a summary.", }; const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": API_KEY, }, body: JSON.stringify(payload), }); const result = await response.json(); console.log(JSON.stringify(result, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Research-Coordinator", "description": "Coordinates parallel research across multiple domains", "system_prompt": "You are a research coordinator. Break down complex research tasks by creating specialized sub-agents for each domain, then delegate research tasks to them and compile a comprehensive report from their findings.", "model_name": "gpt-4.1", "max_loops": "auto", "max_tokens": 8192, "temperature": 0.3 }, "task": "Research the current state of quantum computing. Cover three areas in parallel: 1) Hardware advances, 2) Software and algorithms, 3) Commercial applications. Create a sub-agent for each area, assign research tasks, and compile a summary." }' ``` ### Restricting Sub-Agent Tools You can use `selected_tools` to control exactly which tools the coordinator can access: ```python theme={null} payload = { "agent_config": { "agent_name": "Coordinator", "model_name": "gpt-4.1", "max_loops": "auto", "selected_tools": [ "create_plan", "think", "create_sub_agent", "assign_task", "subtask_done", "complete_task" ] }, "task": "Your task here" } ``` The full list of available tools for autonomous agents: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. The `run_bash` tool is not permitted. ## Pre-Defined Sub-Agents with `handoffs` If you already know which specialists an agent needs, you can define them up front with the `handoffs` field on `agent_config` instead of having the coordinator create them at runtime. `handoffs` takes a list of full agent specifications (the same shape as `agent_config`); these agents are created with the request and the parent agent can hand tasks off to them during execution. Unlike `create_sub_agent`, this does not require `max_loops="auto"`. ```python theme={null} payload = { "agent_config": { "agent_name": "Support-Triage", "description": "Routes customer issues to the right specialist", "model_name": "gpt-4.1", "max_loops": 1, "handoffs": [ { "agent_name": "Billing-Specialist", "description": "Handles billing and refund questions", "system_prompt": "You resolve billing and refund issues.", "model_name": "gpt-4.1" }, { "agent_name": "Technical-Support", "description": "Handles technical product issues", "system_prompt": "You debug and resolve technical product issues.", "model_name": "gpt-4.1" } ] }, "task": "A customer was double-charged last month and also cannot log in. Route this to the right specialists and resolve it." } ``` ## Sub-Agents vs Other Multi-Agent Patterns | Feature | Sub-Agent Delegation | Multi-Agent Swarms | | ------------------ | ------------------------------------------------------------ | --------------------------------------- | | **Agent creation** | Dynamic at runtime | Pre-defined in request | | **Endpoint** | `/v1/agent/completions` | `/v1/swarm/completions` | | **Coordination** | Single coordinator decides | Swarm architecture rules | | **When to use** | Unknown number of agents needed, adaptive task decomposition | Known team structure, fixed workflows | | **Agent count** | Determined by the coordinator at runtime | Specified upfront in the `agents` array | ## Best Practices * **Clear coordinator prompts** — Tell the coordinator explicitly that it should create sub-agents and delegate work. Include guidance on what types of specialists to create. * **3-5 sub-agents** for standard tasks, 5-10 for complex multi-domain projects. More than 10 increases coordination overhead. * **Specific sub-agent descriptions** — The more specific the `agent_description`, the better the sub-agent performs its specialized task. * **Use `wait_for_completion: true`** (default) when the coordinator needs to synthesize results. Use `false` only for fire-and-forget scenarios. * **Set appropriate timeouts** — Sub-agent workflows take longer than single-agent calls since multiple agents run sequentially or in parallel. Use a timeout of 300+ seconds for complex tasks. ## Cost Considerations Sub-agent delegation uses more tokens than a single agent call because: * The coordinator agent uses tokens for planning and synthesis * Each sub-agent uses tokens for its specialized task * Tool calls (create/assign) consume additional tokens For cost-sensitive workloads, consider using a multi-agent swarm with pre-defined agents instead, which avoids the overhead of dynamic agent creation. # Structured Outputs Source: https://docs.swarms.ai/docs/documentation/capabilities/swarms_api_tools Get schema-enforced JSON output from your agents using response_format, and integrate tools for function calling The Swarms API supports two distinct capabilities for controlling agent output: * **Structured Outputs** — enforce a JSON schema on the LLM's response using `llm_args.response_format` * **Tools / Function Calling** — provide tool definitions the LLM can invoke using `tools_list_dictionary` ## Structured Outputs Structured outputs guarantee that an agent's response conforms to a JSON schema you define. This uses the model provider's native `response_format` parameter (e.g., OpenAI's structured outputs), passed through `llm_args` in the agent config. ### How It Works Add a `response_format` object inside `llm_args` in your agent configuration. The API passes this directly to the underlying LLM via LiteLLM. ```json theme={null} { "agent_config": { "agent_name": "Data Extractor", "model_name": "gpt-4o", "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "your_schema", "strict": true, "schema": { "type": "object", "properties": { "field_name": { "type": "string" } }, "required": ["field_name"], "additionalProperties": false } } } } } } ``` *** ### Example: JSON Schema Mode Extract structured data from unstructured text by defining the exact fields you want. ```python theme={null} import requests import json import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json={ "agent_config": { "agent_name": "Company Extractor", "description": "Extracts structured company info from text", "system_prompt": "Extract the requested information from the provided text. Return only the JSON output.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "company_info", "strict": True, "schema": { "type": "object", "properties": { "company_name": { "type": "string", "description": "The name of the company" }, "industry": { "type": "string", "description": "The industry the company operates in" }, "founded_year": { "type": "integer", "description": "The year the company was founded" }, "key_products": { "type": "array", "items": {"type": "string"}, "description": "Main products or services" } }, "required": ["company_name", "industry", "founded_year", "key_products"], "additionalProperties": False } } } } }, "task": "Anthropic is an AI safety company founded in 2021. They are known for building Claude, a family of large language models, and for their research on AI alignment and interpretability." } ) print(json.dumps(response.json(), indent=2)) ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ agent_config: { agent_name: "Company Extractor", description: "Extracts structured company info from text", system_prompt: "Extract the requested information from the provided text. Return only the JSON output.", model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.0, llm_args: { response_format: { type: "json_schema", json_schema: { name: "company_info", strict: true, schema: { type: "object", properties: { company_name: { type: "string", description: "The name of the company" }, industry: { type: "string", description: "The industry the company operates in" }, founded_year: { type: "integer", description: "The year the company was founded" }, key_products: { type: "array", items: { type: "string" }, description: "Main products or services" } }, required: ["company_name", "industry", "founded_year", "key_products"], additionalProperties: false } } } } }, task: "Anthropic is an AI safety company founded in 2021. They are known for building Claude, a family of large language models, and for their research on AI alignment and interpretability." }) }); const result = await response.json(); console.log(JSON.stringify(result, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Company Extractor", "description": "Extracts structured company info from text", "system_prompt": "Extract the requested information from the provided text. Return only the JSON output.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "company_info", "strict": true, "schema": { "type": "object", "properties": { "company_name": { "type": "string", "description": "The name of the company" }, "industry": { "type": "string", "description": "The industry the company operates in" }, "founded_year": { "type": "integer", "description": "The year the company was founded" }, "key_products": { "type": "array", "items": {"type": "string"}, "description": "Main products or services" } }, "required": ["company_name", "industry", "founded_year", "key_products"], "additionalProperties": false } } } } }, "task": "Anthropic is an AI safety company founded in 2021. They are known for building Claude, a family of large language models, and for their research on AI alignment and interpretability." }' ``` #### Expected Response The agent's `outputs` field contains the structured JSON in the `content` field: ```json theme={null} { "job_id": "agent-a563cb00f8034d13bbb0401257cc3f7a", "success": true, "name": "Company Extractor", "outputs": [ { "role": "Company Extractor", "content": "{\"company_name\":\"Anthropic\",\"industry\":\"AI safety and research\",\"founded_year\":2021,\"key_products\":[\"Claude language models\",\"AI alignment research\",\"AI interpretability research\"]}" } ], "usage": { "input_tokens": 85, "output_tokens": 95, "total_tokens": 180, "total_cost": 0.00231 } } ``` The `content` field is a JSON string. Parse it in your application to get the structured object. *** ### Structured Outputs in a Swarm Use structured outputs with multiple agents in a ConcurrentWorkflow. Each agent can have its own `response_format` schema. ```python theme={null} import requests import json import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={ "name": "Market Analysis Swarm", "description": "Parallel market analysis with structured output", "agents": [ { "agent_name": "Risk Assessor", "description": "Evaluates investment risk", "system_prompt": "You are a risk assessment expert. Evaluate the investment risk based on the provided information.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "risk_assessment", "strict": True, "schema": { "type": "object", "properties": { "risk_level": {"type": "string"}, "risk_score": {"type": "number"}, "factors": { "type": "array", "items": {"type": "string"} }, "recommendation": {"type": "string"} }, "required": ["risk_level", "risk_score", "factors", "recommendation"], "additionalProperties": False } } } } }, { "agent_name": "Growth Analyst", "description": "Projects growth potential", "system_prompt": "You are a growth analysis expert. Project the growth potential based on the provided information.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "growth_projection", "strict": True, "schema": { "type": "object", "properties": { "growth_potential": {"type": "string"}, "projected_roi_percent": {"type": "number"}, "time_horizon_months": {"type": "integer"}, "catalysts": { "type": "array", "items": {"type": "string"} } }, "required": ["growth_potential", "projected_roi_percent", "time_horizon_months", "catalysts"], "additionalProperties": False } } } } } ], "max_loops": 1, "swarm_type": "ConcurrentWorkflow", "task": "Analyze NVIDIA as an investment opportunity given their dominance in AI GPU market, recent earnings beat, and current P/E ratio of 65." } ) print(json.dumps(response.json(), indent=2)) ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const response = await fetch(`${BASE_URL}/v1/swarm/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ name: "Market Analysis Swarm", description: "Parallel market analysis with structured output", agents: [ { agent_name: "Risk Assessor", description: "Evaluates investment risk", system_prompt: "You are a risk assessment expert. Evaluate the investment risk based on the provided information.", model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.0, llm_args: { response_format: { type: "json_schema", json_schema: { name: "risk_assessment", strict: true, schema: { type: "object", properties: { risk_level: { type: "string" }, risk_score: { type: "number" }, factors: { type: "array", items: { type: "string" } }, recommendation: { type: "string" } }, required: ["risk_level", "risk_score", "factors", "recommendation"], additionalProperties: false } } } } }, { agent_name: "Growth Analyst", description: "Projects growth potential", system_prompt: "You are a growth analysis expert. Project the growth potential based on the provided information.", model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.0, llm_args: { response_format: { type: "json_schema", json_schema: { name: "growth_projection", strict: true, schema: { type: "object", properties: { growth_potential: { type: "string" }, projected_roi_percent: { type: "number" }, time_horizon_months: { type: "integer" }, catalysts: { type: "array", items: { type: "string" } } }, required: ["growth_potential", "projected_roi_percent", "time_horizon_months", "catalysts"], additionalProperties: false } } } } } ], max_loops: 1, swarm_type: "ConcurrentWorkflow", task: "Analyze NVIDIA as an investment opportunity given their dominance in AI GPU market, recent earnings beat, and current P/E ratio of 65." }) }); const result = await response.json(); console.log(JSON.stringify(result, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Market Analysis Swarm", "description": "Parallel market analysis with structured output", "agents": [ { "agent_name": "Risk Assessor", "description": "Evaluates investment risk", "system_prompt": "You are a risk assessment expert.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "risk_assessment", "strict": true, "schema": { "type": "object", "properties": { "risk_level": {"type": "string"}, "risk_score": {"type": "number"}, "factors": {"type": "array", "items": {"type": "string"}}, "recommendation": {"type": "string"} }, "required": ["risk_level", "risk_score", "factors", "recommendation"], "additionalProperties": false } } } } }, { "agent_name": "Growth Analyst", "description": "Projects growth potential", "system_prompt": "You are a growth analysis expert.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "growth_projection", "strict": true, "schema": { "type": "object", "properties": { "growth_potential": {"type": "string"}, "projected_roi_percent": {"type": "number"}, "time_horizon_months": {"type": "integer"}, "catalysts": {"type": "array", "items": {"type": "string"}} }, "required": ["growth_potential", "projected_roi_percent", "time_horizon_months", "catalysts"], "additionalProperties": false } } } } } ], "max_loops": 1, "swarm_type": "ConcurrentWorkflow", "task": "Analyze NVIDIA as an investment opportunity given their dominance in AI GPU market, recent earnings beat, and current P/E ratio of 65." }' ``` #### Expected Response Each agent returns its own structured output in the `output` array: ```json theme={null} { "job_id": "swarm-3e54b3f41f8f461cbd05bf30d8eaecf8", "status": "success", "swarm_name": "Market Analysis Swarm", "swarm_type": "ConcurrentWorkflow", "output": [ { "role": "Risk Assessor", "content": "{\"risk_level\":\"Moderate\",\"risk_score\":6.5,\"factors\":[\"Dominance in AI GPU market provides a strong competitive advantage.\",\"Recent earnings beat indicates strong financial performance.\",\"High P/E ratio of 65 suggests the stock may be overvalued.\"],\"recommendation\":\"Consider as a growth investment, but monitor the high valuation closely.\"}" }, { "role": "Growth Analyst", "content": "{\"growth_potential\":\"Strong growth due to AI and GPU leadership.\",\"projected_roi_percent\":15,\"time_horizon_months\":12,\"catalysts\":[\"Continued demand for AI and machine learning applications\",\"Expansion in data center and cloud computing markets\",\"New product launches and technological advancements\"]}" } ], "number_of_agents": 2 } ``` *** ## Tools / Function Calling Tools let the LLM invoke functions during execution. This is separate from structured outputs — tools define **actions** the model can take, while structured outputs control the **format** of the model's response. Use `tools_list_dictionary` in the agent config to define available tools using the OpenAI function calling schema. ### Defining Tools Each tool follows the OpenAI function calling format: ```json theme={null} { "type": "function", "function": { "name": "tool_name", "description": "What this tool does", "parameters": { "type": "object", "properties": { "param_name": { "type": "string", "description": "Parameter description" } }, "required": ["param_name"] } } } ``` ### Example: Agent with Tools ```python theme={null} import requests import json import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json={ "agent_config": { "agent_name": "Market Analyst", "description": "Analyzes market trends using search tools", "system_prompt": "You are a financial analyst expert. Use the search tool to gather information before providing analysis.", "model_name": "openai/gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct an in-depth search on a specified topic", "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": "Search depth (1-3)" }, "detailed_queries": { "type": "array", "items": { "type": "string", "description": "Specific search queries" } } }, "required": ["depth", "detailed_queries"] } } } ] }, "task": "What are the best ETFs and index funds for AI and tech?" } ) print(json.dumps(response.json(), indent=2)) ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ agent_config: { agent_name: "Market Analyst", description: "Analyzes market trends using search tools", system_prompt: "You are a financial analyst expert. Use the search tool to gather information before providing analysis.", model_name: "openai/gpt-4.1", max_loops: 1, max_tokens: 8192, temperature: 0.5, tools_list_dictionary: [ { type: "function", function: { name: "search_topic", description: "Conduct an in-depth search on a specified topic", parameters: { type: "object", properties: { depth: { type: "integer", description: "Search depth (1-3)" }, detailed_queries: { type: "array", items: { type: "string", description: "Specific search queries" } } }, required: ["depth", "detailed_queries"] } } } ] }, task: "What are the best ETFs and index funds for AI and tech?" }) }); const result = await response.json(); console.log(JSON.stringify(result, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Market Analyst", "description": "Analyzes market trends using search tools", "system_prompt": "You are a financial analyst expert. Use the search tool to gather information before providing analysis.", "model_name": "openai/gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct an in-depth search on a specified topic", "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": "Search depth (1-3)" }, "detailed_queries": { "type": "array", "items": {"type": "string", "description": "Specific search queries"} } }, "required": ["depth", "detailed_queries"] } } } ] }, "task": "What are the best ETFs and index funds for AI and tech?" }' ``` #### Expected Response When the model calls a tool, the `content` field contains the tool call arguments: ```json theme={null} { "job_id": "agent-f424ee9035fb41b99b72459a55683eeb", "success": true, "name": "Market Analyst", "outputs": [ { "role": "Market Analyst", "content": [ { "function": { "arguments": "{\"depth\":2,\"detailed_queries\":[\"best ETFs for AI and technology\",\"top index funds for technology sector\"]}", "name": "search_topic" }, "id": "call_efaxUkKmjKYHryMKZMnQBvdi", "type": "function" } ] } ], "usage": { "input_tokens": 115, "output_tokens": 146, "total_tokens": 261, "total_cost": 0.003448 } } ``` ### Parsing Tool Call Responses When an agent calls a tool, the `content` field is an **array of tool call objects** (not a plain string like structured outputs). Each object contains: | Field | Type | Description | | -------------------- | -------- | -------------------------------------------------------- | | `function.name` | `string` | The name of the tool the model wants to call | | `function.arguments` | `string` | A JSON-encoded string containing the tool call arguments | | `id` | `string` | A unique identifier for this tool call | | `type` | `string` | Always `"function"` | The `arguments` field is a **JSON string**, not a parsed object. You must parse it with `json.loads()` (Python) or `JSON.parse()` (JavaScript) before using the values. #### Step-by-Step Parsing ```python theme={null} import requests import json import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } # 1. Send the request with tool definitions response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json={ "agent_config": { "agent_name": "Weather Assistant", "description": "Gets weather information", "system_prompt": "You are a weather assistant. Use the get_weather tool to answer questions.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 4096, "temperature": 0.0, "tools_list_dictionary": [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a given location", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "City name, e.g. San Francisco, CA" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature unit" } }, "required": ["location"] } } } ] }, "task": "What is the weather in San Francisco?" } ) data = response.json() # 2. Extract tool calls from the response agent_output = data["outputs"][0] tool_calls = agent_output["content"] # This is a list of tool call objects # 3. Parse each tool call for tool_call in tool_calls: function_name = tool_call["function"]["name"] call_id = tool_call["id"] # Parse the arguments JSON string into a Python dict arguments = json.loads(tool_call["function"]["arguments"]) print(f"Tool: {function_name}") print(f"Call ID: {call_id}") print(f"Arguments: {arguments}") # 4. Use the parsed arguments in your application if function_name == "get_weather": location = arguments["location"] unit = arguments.get("unit", "fahrenheit") print(f" → Fetching weather for {location} in {unit}") # Call your actual weather API here ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; // 1. Send the request with tool definitions const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: "POST", headers: { "x-api-key": API_KEY!, "Content-Type": "application/json" }, body: JSON.stringify({ agent_config: { agent_name: "Weather Assistant", description: "Gets weather information", system_prompt: "You are a weather assistant. Use the get_weather tool to answer questions.", model_name: "gpt-4.1", max_loops: 1, max_tokens: 4096, temperature: 0.0, tools_list_dictionary: [ { type: "function", function: { name: "get_weather", description: "Get the current weather for a given location", parameters: { type: "object", properties: { location: { type: "string", description: "City name, e.g. San Francisco, CA" }, unit: { type: "string", enum: ["celsius", "fahrenheit"], description: "Temperature unit" } }, required: ["location"] } } } ] }, task: "What is the weather in San Francisco?" }) }); const data = await response.json(); // 2. Extract tool calls from the response const agentOutput = data.outputs[0]; const toolCalls = agentOutput.content; // Array of tool call objects // 3. Parse each tool call for (const toolCall of toolCalls) { const functionName = toolCall.function.name; const callId = toolCall.id; // Parse the arguments JSON string into an object const args = JSON.parse(toolCall.function.arguments); console.log(`Tool: ${functionName}`); console.log(`Call ID: ${callId}`); console.log(`Arguments:`, args); // 4. Use the parsed arguments in your application if (functionName === "get_weather") { const location = args.location; const unit = args.unit ?? "fahrenheit"; console.log(` → Fetching weather for ${location} in ${unit}`); // Call your actual weather API here } } ``` #### Example Output ``` Tool: get_weather Call ID: call_VPqXFY3bgFsTJHLQeeQYY230 Arguments: {'location': 'San Francisco, CA'} → Fetching weather for San Francisco, CA in fahrenheit ``` **Detecting tool calls vs. text responses:** When the agent uses tools, `content` is an array of objects. When the agent responds with plain text, `content` is a string. Check the type to handle both cases: ```python theme={null} content = data["outputs"][0]["content"] if isinstance(content, list): # Agent made tool call(s) — parse them for tool_call in content: args = json.loads(tool_call["function"]["arguments"]) elif isinstance(content, str): # Agent responded with text print(content) ``` *** ### Multi-Agent Swarm with Tools Combine multiple tool-enabled agents in a swarm. Each agent can have its own set of tools. ```python theme={null} import requests import json import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={ "name": "Financial Analysis Swarm", "description": "Multi-agent financial analysis with tools", "agents": [ { "agent_name": "Market Analyst", "description": "Analyzes market trends", "system_prompt": "You are a financial analyst expert.", "model_name": "openai/gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct market research", "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": "Search depth (1-3)" }, "detailed_queries": { "type": "array", "items": {"type": "string"} } }, "required": ["depth", "detailed_queries"] } } } ] }, { "agent_name": "Economic Forecaster", "description": "Predicts economic trends", "system_prompt": "You are an expert in economic forecasting.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct economic research", "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": "Search depth (1-3)" }, "detailed_queries": { "type": "array", "items": {"type": "string"} } }, "required": ["depth", "detailed_queries"] } } } ] } ], "max_loops": 1, "swarm_type": "ConcurrentWorkflow", "task": "Analyze top performing tech ETFs and their growth potential" } ) print(json.dumps(response.json(), indent=2)) ``` ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const response = await fetch(`${BASE_URL}/v1/swarm/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ name: "Financial Analysis Swarm", description: "Multi-agent financial analysis with tools", agents: [ { agent_name: "Market Analyst", description: "Analyzes market trends", system_prompt: "You are a financial analyst expert.", model_name: "openai/gpt-4.1", max_loops: 1, max_tokens: 8192, temperature: 0.5, tools_list_dictionary: [ { type: "function", function: { name: "search_topic", description: "Conduct market research", parameters: { type: "object", properties: { depth: { type: "integer", description: "Search depth (1-3)" }, detailed_queries: { type: "array", items: { type: "string" } } }, required: ["depth", "detailed_queries"] } } } ] }, { agent_name: "Economic Forecaster", description: "Predicts economic trends", system_prompt: "You are an expert in economic forecasting.", model_name: "gpt-4.1", max_loops: 1, max_tokens: 8192, temperature: 0.5, tools_list_dictionary: [ { type: "function", function: { name: "search_topic", description: "Conduct economic research", parameters: { type: "object", properties: { depth: { type: "integer", description: "Search depth (1-3)" }, detailed_queries: { type: "array", items: { type: "string" } } }, required: ["depth", "detailed_queries"] } } } ] } ], max_loops: 1, swarm_type: "ConcurrentWorkflow", task: "Analyze top performing tech ETFs and their growth potential" }) }); const result = await response.json(); console.log(JSON.stringify(result, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Financial Analysis Swarm", "description": "Multi-agent financial analysis with tools", "agents": [ { "agent_name": "Market Analyst", "description": "Analyzes market trends", "system_prompt": "You are a financial analyst expert.", "model_name": "openai/gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct market research", "parameters": { "type": "object", "properties": { "depth": {"type": "integer", "description": "Search depth (1-3)"}, "detailed_queries": {"type": "array", "items": {"type": "string"}} }, "required": ["depth", "detailed_queries"] } } } ] }, { "agent_name": "Economic Forecaster", "description": "Predicts economic trends", "system_prompt": "You are an expert in economic forecasting.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct economic research", "parameters": { "type": "object", "properties": { "depth": {"type": "integer", "description": "Search depth (1-3)"}, "detailed_queries": {"type": "array", "items": {"type": "string"}} }, "required": ["depth", "detailed_queries"] } } } ] } ], "max_loops": 1, "swarm_type": "ConcurrentWorkflow", "task": "Analyze top performing tech ETFs and their growth potential" }' ``` #### Expected Response ```json theme={null} { "job_id": "swarm-884b618ebadc4b2a9c80a0660a3fb928", "status": "success", "swarm_name": "Financial Analysis Swarm", "swarm_type": "ConcurrentWorkflow", "output": [ { "role": "Market Analyst", "content": "[{\"function\": {\"arguments\": \"{\\\"depth\\\":3,\\\"detailed_queries\\\":[\\\"Top performing tech ETFs\\\",\\\"Growth potential of tech ETFs\\\"]}\", \"name\": \"search_topic\"}, \"type\": \"function\"}]" }, { "role": "Economic Forecaster", "content": "[{\"function\": {\"arguments\": \"{\\\"depth\\\":2,\\\"detailed_queries\\\":[\\\"Top performing tech ETFs\\\",\\\"Factors influencing tech ETF performance\\\"]}\", \"name\": \"search_topic\"}, \"type\": \"function\"}]" } ], "number_of_agents": 2 } ``` ### Parsing Swarm Tool Calls Swarm responses differ from single-agent responses in two ways: 1. The response key is **`output`** (not `outputs`) 2. The `content` field is a **string** (serialized Python representation), not a native array Use `ast.literal_eval` in Python to safely parse the content string: ```python theme={null} import ast import json data = response.json() for agent_output in data["output"]: agent_name = agent_output["role"] content = agent_output["content"] # Swarm content is a string — parse it into a list if isinstance(content, str): tool_calls = ast.literal_eval(content) else: tool_calls = content for tool_call in tool_calls: function_name = tool_call["function"]["name"] arguments = json.loads(tool_call["function"]["arguments"]) print(f"[{agent_name}] Tool: {function_name}") print(f" Arguments: {arguments}") ``` ```typescript theme={null} const data = await response.json(); for (const agentOutput of data.output) { const agentName = agentOutput.role; let content = agentOutput.content; // Swarm content is a string — parse it into an array let toolCalls: any[]; if (typeof content === "string") { // Replace Python-style single quotes with double quotes for JSON parsing const jsonString = content.replace(/'/g, '"'); toolCalls = JSON.parse(jsonString); } else { toolCalls = content; } for (const toolCall of toolCalls) { const functionName = toolCall.function.name; const args = JSON.parse(toolCall.function.arguments); console.log(`[${agentName}] Tool: ${functionName}`); console.log(` Arguments:`, args); } } ``` *** ## FAQ **Structured outputs** (`llm_args.response_format`) control the *format* of the model's response — you define a JSON schema and the model's output is guaranteed to match it. **Tools** (`tools_list_dictionary`) define *actions* the model can invoke — the model decides when to call a function and with what arguments. You can use both on the same agent if needed. No, tools are optional for each agent. Simply omit the `tools_list_dictionary` field for agents that don't require tools. Structured outputs via `response_format` work with models that support OpenAI's structured output format, including `gpt-4.1`, `gpt-4.1-mini`, and `gpt-4o`. The feature is passed through LiteLLM, so any LiteLLM-supported model with `response_format` support will work. Yes. Set `llm_args.response_format` for the output format and `tools_list_dictionary` for available tools on the same agent. # Streaming Source: https://docs.swarms.ai/docs/documentation/capabilities/tools Real-time streaming responses for immediate agent feedback and better user experience The Swarms API supports real-time streaming responses, allowing you to receive agent outputs as they're generated. This provides immediate feedback and a better user experience for long-running tasks. Streaming is enabled by setting `"streaming_on": true` in your agent configuration. ## Quick Start Enable streaming by adding the `streaming_on` parameter to your agent configuration: ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" } payload = { "agent_config": { "agent_name": "Research Analyst", "model_name": "claude-sonnet-4-20250514", "max_tokens": 8192, "streaming_on": True }, "task": "What are the key trends in AI development?" } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, stream=True ) ``` ```javascript theme={null} const fetch = require('node-fetch'); require('dotenv').config(); const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" }; const payload = { agent_config: { agent_name: "Research Analyst", model_name: "claude-sonnet-4-20250514", max_tokens: 8192, streaming_on: true }, task: "What are the key trends in AI development?" }; const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -H "Connection: keep-alive" \ -H "X-Accel-Buffering: no" \ -d '{ "agent_config": { "agent_name": "Research Analyst", "model_name": "claude-sonnet-4-20250514", "max_tokens": 8192, "streaming_on": true }, "task": "What are the key trends in AI development?" }' \ --no-buffer -N ``` ## Stream Format The API uses Server-Sent Events (SSE) format. Each frame is a `data:` line, optionally preceded by an `event:` line naming the event type. The very first frame (job metadata) is sent **without** an `event:` line — identify it by `"type": "metadata"` inside the payload: ``` data: {"job_id": "abc123", "success": true, "name": "Research Analyst", "temperature": 0.7, "stream": true, "type": "metadata"} event: start data: {"message": "Starting agent processing..."} event: chunk data: {"content": "Based on current research", "timestamp": "2026-07-09T12:00:00Z"} event: chunk data: {"content": ", AI development shows", "timestamp": "2026-07-09T12:00:01Z"} event: usage data: {"input_tokens": 42, "output_tokens": 108, "total_tokens": 150, "img_cost": 0, "total_cost": 0.00075} event: end data: {"job_id": "abc123", "usage": {"...": "..."}, "timestamp": "2026-07-09T12:00:02Z", "complete": true} event: done data: {"message": "Agent processing complete"} ``` On failure, a single `error` event is sent instead of `usage`/`end`/`done`: ``` event: error data: {"error": "AgentCompletionError: ...", "timestamp": "2026-07-09T12:00:02Z"} ``` ## Parsing Streams Here's how to parse streaming responses in different languages: ```python theme={null} def parse_streaming_response(response): """Parse streaming response and handle events""" full_content = "" current_event = None for line in response.iter_lines(): if not line: continue line = line.decode("utf-8") # Parse event type if line.startswith("event: "): current_event = line[7:].strip() continue # Parse event data elif line.startswith("data: "): try: data = json.loads(line[6:]) # The first frame has no "event:" line — identify it by # its "type" field instead. if current_event is None and data.get("type") == "metadata": print(f"Job ID: {data.get('job_id')}") print(f"Agent: {data.get('name')}") print("-" * 40) elif current_event == "start": print(data.get("message", "Starting...")) elif current_event == "chunk": content = data.get("content", "") full_content += content print(content, end="", flush=True) elif current_event == "usage": print(f"\nTokens used: {data.get('total_tokens')}") print(f"Cost: ${data.get('total_cost', 0):.4f}") elif current_event == "end": print(f"\nJob {data.get('job_id')} complete") elif current_event == "done": print("\n✅ Complete!") elif current_event == "error": print(f"\n❌ Error: {data.get('error')}") except json.JSONDecodeError: continue return full_content ``` ```javascript theme={null} async function parseStreamingResponse(response) { let fullContent = ""; let currentEvent = null; const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('event: ')) { currentEvent = line.substring(7).trim(); continue; } if (line.startsWith('data: ')) { try { const data = JSON.parse(line.substring(6)); // The first frame has no "event: " line — identify it // by its "type" field instead. if (currentEvent === null && data.type === 'metadata') { console.log(`Job ID: ${data.job_id}`); console.log(`Agent: ${data.name}`); console.log("-".repeat(40)); } else if (currentEvent === 'start') { console.log(data.message || "Starting..."); } else if (currentEvent === 'chunk') { const content = data.content || ""; fullContent += content; process.stdout.write(content); } else if (currentEvent === 'usage') { console.log(`\nTokens used: ${data.total_tokens}`); console.log(`Cost: $${data.total_cost?.toFixed(4) || 0}`); } else if (currentEvent === 'end') { console.log(`\nJob ${data.job_id} complete`); } else if (currentEvent === 'done') { console.log("\n✅ Complete!"); } else if (currentEvent === 'error') { console.log(`\n❌ Error: ${data.error}`); } } catch (e) { // Skip malformed JSON } } } } return fullContent; } ``` ```go theme={null} func parseStreamingResponse(body io.Reader) { scanner := bufio.NewScanner(body) var currentEvent string var fullContent strings.Builder for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, "event: ") { currentEvent = strings.TrimSpace(line[7:]) continue } if strings.HasPrefix(line, "data: ") { var data StreamData if err := json.Unmarshal([]byte(line[6:]), &data); err != nil { continue } switch currentEvent { case "": // The first frame has no "event: " line — identify it by // its "type" field instead. if data.Type == "metadata" { fmt.Printf("Job ID: %s\n", data.JobID) fmt.Printf("Agent: %s\n", data.Name) fmt.Println(strings.Repeat("-", 40)) } case "chunk": fullContent.WriteString(data.Content) fmt.Print(data.Content) case "usage": fmt.Printf("\nTokens used: %d\n", data.TotalTokens) fmt.Printf("Cost: $%.4f\n", data.TotalCost) case "done": fmt.Println("\n✅ Complete!") case "error": fmt.Printf("\n❌ Error: %s\n", data.Error) } } } fmt.Printf("\n📝 Total content: %d characters\n", fullContent.Len()) } ``` ## Complete Examples ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() def run_streaming_agent(): """Complete example of streaming agent request""" API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" } payload = { "agent_config": { "agent_name": "Research Analyst", "model_name": "claude-sonnet-4-20250514", "max_tokens": 8192, "streaming_on": True }, "task": "What are the best ways to find samples of diabetes from blood samples?" } print("🚀 Starting streaming request...") response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, stream=True, timeout=60 ) if response.status_code != 200: print(f"❌ Error: {response.status_code} - {response.text}") return # Parse the streaming response full_content = parse_streaming_response(response) print(f"\n📝 Total content: {len(full_content)} characters") # Run the example if __name__ == "__main__": run_streaming_agent() ``` ```javascript theme={null} const fetch = require('node-fetch'); require('dotenv').config(); async function runStreamingAgent() { const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" }; const payload = { agent_config: { agent_name: "Research Analyst", model_name: "claude-sonnet-4-20250514", max_tokens: 8192, streaming_on: true }, task: "What are the best ways to find samples of diabetes from blood samples?" }; console.log("🚀 Starting streaming request..."); try { const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }); if (!response.ok) { console.error(`❌ Error: ${response.status} - ${await response.text()}`); return; } // Parse streaming response const fullContent = await parseStreamingResponse(response); console.log(`\n📝 Total content: ${fullContent.length} characters`); } catch (error) { console.error("Request failed:", error); } } // Run the example runStreamingAgent(); ``` ```bash theme={null} #!/bin/bash API_KEY="your-api-key-here" BASE_URL="https://api.swarms.world" echo "🚀 Starting streaming request..." curl -X POST "${BASE_URL}/v1/agent/completions" \ -H "x-api-key: ${API_KEY}" \ -H "Content-Type: application/json" \ -H "Connection: keep-alive" \ -H "X-Accel-Buffering: no" \ -d '{ "agent_config": { "agent_name": "Research Analyst", "model_name": "claude-sonnet-4-20250514", "max_tokens": 8192, "streaming_on": true }, "task": "What are the best ways to find samples of diabetes from blood samples?" }' \ --no-buffer \ -N ``` ## Event Types | Event | Description | Data Fields | | ---------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | *(none — first frame)* | Job metadata, sent before any `event:` line | `job_id`, `success`, `name`, `description`, `temperature`, `timestamp`, `stream`, `type` (`"metadata"`) | | `start` | Agent processing has begun | `message` | | `chunk` | Content piece | `content`, `timestamp` | | `usage` | Token usage and cost, sent once near the end | `input_tokens`, `output_tokens`, `total_tokens`, `img_cost`, `total_cost` | | `end` | Final job metadata | `job_id`, `usage`, `timestamp`, `complete` | | `done` | Stream finished | `message` | | `error` | Error info | `error`, `timestamp` | ## Best Practices ### Error Handling Always handle potential errors in your stream processing: ```python theme={null} try: response = requests.post(url, json=payload, stream=True, timeout=60) if response.status_code != 200: print(f"Error: {response.status_code} - {response.text}") return full_content = parse_streaming_response(response) except requests.exceptions.RequestException as e: print(f"Request failed: {e}") except json.JSONDecodeError as e: print(f"JSON decode error: {e}") ``` ### Timeout Management Set appropriate timeouts for your use case: ```python theme={null} # For quick responses response = requests.post(url, json=payload, stream=True, timeout=30) # For long-running tasks response = requests.post(url, json=payload, stream=True, timeout=300) ``` ## Benefits * **Real-time Feedback**: See results as they're generated * **Better UX**: Reduced perceived latency * **Progress Tracking**: Monitor long-running operations * **Error Handling**: Immediate error feedback ## Troubleshooting Increase timeout values for long-running tasks. Set appropriate timeouts based on your expected response time. Handle malformed data gracefully by wrapping JSON parsing in try-catch blocks. Always check for `done` or `error` events to ensure the stream completed successfully. Process chunks incrementally for large responses to avoid memory issues. ### Debug Mode Enable debug logging to troubleshoot stream issues: ```python theme={null} import logging logging.basicConfig(level=logging.DEBUG) ``` # Changelog Source: https://docs.swarms.ai/docs/documentation/changelog Product updates and announcements # August 19, 2026 Updates ## Limits * **raise the agent batch limit to 50** - Kye Gomez * **bound roster size and loop count on a swarm request** - ayaangazali # August 17, 2026 Updates ## Endpoints * **move premium listing to /v1/account/premium-endpoints; alias /v1/swarm/logs to /v1/account/logs** - Kye Gomez # August 6, 2026 Updates ## Features * **add /v1/auto-agent-builder/completions endpoint** - Steve-Dusty # August 1, 2026 Updates ## Models * **make claude-sonnet-5 the base model** - Kye Gomez * **restrict only frontier models for free tier** - Kye Gomez # July 29, 2026 Updates ## Defaults * **raise max tokens to 16000** - Kye Gomez * **accept low through max reasoning effort tiers** - Kye Gomez # July 27, 2026 Updates ## Features * **expose agent fallback models with matching validation** - Steve-Dusty # July 24, 2026 Updates ## Features * **add per-swarm-type metadata to /v1/swarms/available** - Steve-Dusty # July 11, 2026 Updates ## Limits * **block requests below minimum credit balance** - Kye Gomez # July 6, 2026 Updates ## Rate Limits * **Increase maximum requests per hour limit to 350** - CI-DEV ## Features * **add user metrics summary endpoint** - Kye Gomez # July 3, 2026 Updates ## Features * **OpenAI-compatible GET /v1/models endpoint** - Kye Gomez # June 21, 2026 Updates ## Removals * **remove the marketplace endpoint** - Steve-Dusty # June 19, 2026 Updates ## Removals * **remove auto swarm builder endpoint and code** - Kye Gomez # June 15, 2026 Updates ## Removals * **drop advanced research endpoints and module** - Kye Gomez # May 28, 2026 Updates ## Defaults * **omit temperature when caller does not set it; schema default is now none** - Kye Gomez # April 20, 2026 Updates ## Features * **add X-RateLimit-* headers to all API responses*\* - Steve-Dusty # March 24, 2026 Updates ## Features * **Add /v1/chat/completions endpoint (OpenAI-compatible)** - Steve-Dusty # March 23, 2026 Updates ## Removals * **delete un-used /v1/swarm/types** - Kye Gomez # January 26, 2026 Updates ## Features * **Handoffs in the agent spec** - Kye Gomez # January 6, 2026 Updates ## Pricing * **Consolidate pricing into UsagePricingModel and enhance /v1/usage/costs endpoint** - Kye Gomez # December 12, 2025 Updates ## Removals * **remove redundant swarm type and fetch it from swarms router (AutoSwarmBuilder is no longer an accepted swarm\_type)** - Kye Gomez # October 23, 2025 Updates ## Cleanup * **cleanup and re download swarms** - Kye Gomez * **code formatting** - Kye Gomez ## Issues * **new issues** - Kye Gomez # October 22, 2025 Updates ## Tests * **Improve main tests.py** - Kye Gomez * **New Tests** - Kye Gomez * **Reasoning Agents tests** - Kye Gomez * **refactored tests.py to use pytest, removed md summary** - Steve-Dusty ## Fixes * **fix bad error logs** - Kye Gomez * **fix broken error log** - Kye Gomez * **Fix the error logs** - Kye Gomez ## Improvements * **On startup lifepsan manager for sentry** - Kye Gomez * **Improve model restrictions and also improve error message logs** - Kye Gomez * **remove more un-usable models** - Kye Gomez * **LZ4Middleware -> DynamicMiddleware** - Kye Gomez * **CLEANUP TESTS** - Kye Gomez ## Pull Requests * **Merge pull request #68 from Steve-Dusty/main** - Kye Gomez * **Merge pull request #65 from IlumCI/api-restrict** - Kye Gomez * **Merge pull request #67 from Steve-Dusty/main** - Kye Gomez # October 21, 2025 Updates ## Features * **Docker compose** - Kye Gomez ## Documentation * **Update README.md** - Kye Gomez ## Other Changes * **Update model restrictions and pricing links** - CI-DEV * **Merge branch 'The-Swarm-Corporation:main' into api-restrict** - CI-DEV # October 20, 2025 Updates ## Tests * **refactored tests/tests.py to pytest in pure functions** - Steve-Dusty * **added tests for gh workflows** - Steve-Dusty ## Features * **added limit enforcement, daily requests from 1200 to 400/day and limited max context token from 200K to 75K/agent** - Steve-Dusty * **reverted limit enforcement to before** - Steve-Dusty * **Implement restricted models for free tier users** - CI-DEV ## Other Changes * **Update utils.py** - CI-DEV # October 16, 2025 Updates ## Documentation * **fix readme** - Kye Gomez # October 9, 2025 Updates ## Cleanup * **cleanup** - Kye Gomez ## Docker * **dockerfile with free threaded python3.14t verison** - Kye Gomez # October 7, 2025 Updates ## Features * **rate limits for all of a users api keys** - Kye Gomez * **lzav** - Kye Gomez * **new lz4 middleware** - Kye Gomez ## Performance * **removed torch and transformers for faster build times** - Kye Gomez ## Documentation * **docs cleanup** - Kye Gomez # September 26, 2025 Updates ## Features * **full port** - Kye Gomez ## Tests * **updated tests** - Kye Gomez ## Cleanup * **remove premium models** - Kye Gomez * **fix get user logs, cleanup examples, and more** - Kye Gomez # September 8, 2025 Updates ## Other Changes * **just update to date** - Kye Gomez # September 3, 2025 Updates ## Fixes * **heavy swarm check** - Kye Gomez * **heavy swarm issue** - Kye Gomez # September 2, 2025 Updates ## Features * **Streaming for agent completions** - Kye Gomez * **Examples** - Kye Gomez * **Tools fix** - Kye Gomez * **tools endpoint update** - Kye Gomez * **Search Enabled** - Kye Gomez * **EXA Integration from swarms-tools** - Kye Gomez * **NEW ENDPOINT to get available tools** - Kye Gomez * **improvement** - Kye Gomez * **agent validation function** - Kye Gomez ## Documentation * **new cloud deployment docs** - Kye Gomez * **multi region cloud deployment and new examples** - Kye Gomez ## Docker * **UPDATE DOCKER TO FIX SWARMS TOOLS** - Kye Gomez * **fix tool names** - Kye Gomez ## Other Changes * **cleanup examples** - Kye Gomez # August 31, 2025 Updates ## Cleanup * **cleanup examples** - Kye Gomez # August 23, 2025 Updates ## Docker * **update docker config** - Kye Gomez ## Cleanup * **cleanup** - Kye Gomez ## Fixes * **fix example** - Kye Gomez # August 17, 2025 Updates ## Fixes * **fix scripts not found error in docker** - Kye Gomez ## Docker * **no uv in docker** - Kye Gomez ## Features * **LZ4Middleware** - Kye Gomez * **Dynamic middleware that uses lz4 or gzip** - Kye Gomez * **AdvancedResearch** - Kye Gomez * **fix** - Kye Gomez * **agent.job\_id issue** - Kye Gomez # August 6, 2025 Updates ## Features * **HeavySwarm Enablement** - Kye Gomez * **BaseModel Response for rate limits endpoint** - Kye Gomez ## Tests * **tests** - Kye Gomez ## Performance * **file cleanup** - Kye Gomez * **fix api issues** - Kye Gomez * **artifact cleanup** - Kye Gomez * **uv install and setup** - Kye Gomez * **fix worker count for gunicorn** - Kye Gomez * **enhanced error logging for api key configuration** - Kye Gomez * **fix check model name parmaeter** - Kye Gomez # August 5, 2025 Updates ## Features * **BaseModel Response for rate limits endpoint** - Kye Gomez * **enhanced error logging for api key configuration** - Kye Gomez * **fix check model name parmaeter** - Kye Gomez # August 2, 2025 Updates ## Cleanup * **Cleanup** - Kye Gomez # July 31, 2025 Updates ## Fixes * **redeploy** - Kye Gomez * **fix agent.description to agent\_description** - Kye Gomez ## Pull Requests * **Merge pull request #50 from The-Swarm-Corporation/dependabot/github\_actions/actions/first-interaction-2.0.0** - Kye Gomez # July 30, 2025 Updates ## Cleanup * **cleanup** - Kye Gomez * **code cleanup** - Kye Gomez ## Features * **fix agent description parameter** - Kye Gomez ## Performance * **gunicorn test again** - Kye Gomez * **use orjson** - Kye Gomez # July 28, 2025 Updates ## Dependencies * **Bump actions/first-interaction from 1.3.0 to 2.0.0** - dependabot\[bot] # Python Client Source: https://docs.swarms.ai/docs/documentation/clients/python-client Official Python client library for the Swarms API with comprehensive features and examples ## Features * **Type Safety**: Full type definitions for all request params and response fields * **Dual Clients**: Both synchronous and asynchronous clients powered by httpx * **Comprehensive Coverage**: Access to all Swarms API endpoints * **Modern Python**: Built for Python 3.8+ with async/await support * **Environment Integration**: Seamless .env file support for API keys ## Installation ```bash theme={null} pip install swarms-client ``` ## Environment Setup Create a `.env` file in your project root: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Quick Start ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) ``` ### Your First Swarm ```python theme={null} # Define your task task_description = """ Analyze the following patient symptoms and provide ICD code recommendations: - 45-year-old female with chest pain - Shortness of breath for 2 days - Sharp chest pain worsening with deep breathing - Mild fever (100.2°F) and dry cough """ # Create and run a swarm response = client.swarms.run( name="Medical Analysis Swarm", description="A swarm that analyzes patient symptoms and provides ICD codes", swarm_type="ConcurrentWorkflow", task=task_description, agents=[ { "agent_name": "Symptom Analyzer", "description": "Analyzes patient symptoms and identifies key indicators", "system_prompt": "You are a medical expert. Analyze symptoms and identify key medical indicators.", "model_name": "groq/openai/gpt-oss-120b", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "ICD Code Specialist", "description": "Provides appropriate ICD codes based on symptom analysis", "system_prompt": "You are an ICD coding specialist. Provide accurate ICD codes with explanations.", "model_name": "groq/openai/gpt-oss-120b", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.2, } ], ) print(response) ``` ## Client Configuration ### Environment Variable Set `SWARMS_API_KEY` in your environment (or a `.env` file), then load it in your code: ```python theme={null} import os from dotenv import load_dotenv load_dotenv() client = SwarmsClient() # Automatically uses SWARMS_API_KEY from environment ``` ### Direct API Key ```python theme={null} client = SwarmsClient(api_key="your_api_key_here") ``` ### Custom Configuration ```python theme={null} client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", # Optional custom base URL timeout=30.0, # Request timeout in seconds ) ``` ## Core Operations ### Swarm Management ```python theme={null} # Create and run a swarm swarm_response = client.swarms.run( name="Data Analysis Swarm", description="Analyzes complex datasets", swarm_type="SequentialWorkflow", task="Analyze the sales data for Q4", agents=[...] ) # Get swarm logs logs = client.swarms.get_logs() # Check available swarms available = client.swarms.check_available() ``` ### Model Information ```python theme={null} # List available models models = client.models.list_available() ``` ### Health and Status ```python theme={null} # Check API health health_status = client.health.check() # Get rate limits rate_limits = client.client.rate.get_limits() print(health_status) print(rate_limits) ``` ## Advanced Usage ### Asynchronous Operations ```python theme={null} import asyncio import os from swarms_client import AsyncSwarmsClient async def main(): client = AsyncSwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Run multiple operations concurrently results = await asyncio.gather( client.swarms.run( name="Task 1", swarm_type="ConcurrentWorkflow", task="Analyze customer feedback for Q1", agents=[ { "agent_name": "Feedback Analyst", "system_prompt": "You analyze customer feedback and summarize key themes.", "model_name": "gpt-4.1", } ], ), client.swarms.run( name="Task 2", swarm_type="ConcurrentWorkflow", task="Generate a monthly report summary", agents=[ { "agent_name": "Report Writer", "system_prompt": "You write concise executive report summaries.", "model_name": "gpt-4.1", } ], ), client.models.list_available(), ) return results # Run the async function results = asyncio.run(main()) ``` ### Batch Operations ```python theme={null} # Process multiple tasks tasks = [ "Analyze customer feedback for Q1", "Generate monthly report summary", "Review system performance metrics" ] responses = [] for task in tasks: response = client.swarms.run( name=f"Batch Task - {task[:20]}...", description="Batch processing task", swarm_type="ConcurrentWorkflow", task=task, agents=[...] ) responses.append(response) ``` ## Helper Methods The client provides convenient helper methods for common operations: ```python theme={null} # Quick health check if client.health.check()['status'] == 'ok': print("API is healthy!") # Get available models with formatting models = client.models.list_available() print(f"Available models: {models['count']}") # Check rate limits limits = client.client.rate.get_limits() minute = limits['rate_limits']['minute'] print(f"Current usage (last minute): {minute['count']}/{minute['limit']}") print(f"Tier: {limits['tier']}") ``` ## Examples ### Content Generation Swarm ```python theme={null} content_swarm = client.swarms.run( name="Content Generation Swarm", description="Creates engaging content for social media", swarm_type="SequentialWorkflow", task="Create a blog post about AI trends in 2024", agents=[ { "agent_name": "Research Agent", "description": "Researches current AI trends and statistics", "system_prompt": "You are a research specialist. Gather current information about AI trends.", "model_name": "groq/openai/gpt-oss-120b", "role": "researcher", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Writer Agent", "description": "Writes engaging blog content based on research", "system_prompt": "You are a professional writer. Create engaging blog content.", "model_name": "groq/openai/gpt-oss-120b", "role": "writer", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, } ], ) ``` ### Data Analysis Pipeline ```python theme={null} analysis_pipeline = client.swarms.run( name="Data Analysis Pipeline", description="Comprehensive data analysis workflow", swarm_type="SequentialWorkflow", task="Analyze quarterly sales data and provide insights", agents=[ { "agent_name": "Data Validator", "description": "Validates and cleans input data", "system_prompt": "You are a data validation expert. Check data quality and format.", "model_name": "groq/openai/gpt-oss-120b", "role": "validator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.1, }, { "agent_name": "Statistical Analyst", "description": "Performs statistical analysis on the data", "system_prompt": "You are a statistical analyst. Perform comprehensive data analysis.", "model_name": "groq/openai/gpt-oss-120b", "role": "analyst", "max_loops": 1, "max_tokens": 8192, "temperature": 0.2, }, { "agent_name": "Insight Generator", "description": "Generates actionable insights from analysis", "system_prompt": "You are a business analyst. Generate actionable insights.", "model_name": "groq/openai/gpt-oss-120b", "role": "insights", "max_loops": 1, "max_tokens": 4096, "temperature": 0.5, } ], ) ``` ## Troubleshooting ### Common Issues 1. **API Key Errors**: Ensure your API key is valid and properly set in environment variables 2. **Rate Limiting**: Check rate limits with `client.client.rate.get_limits()` 3. **Network Issues**: Verify your internet connection and firewall settings 4. **Model Availability**: Use `client.models.list_available()` to check available models ### Getting Help * **GitHub**: [swarms-client repository](https://github.com/The-Swarm-Corporation/swarms-client) * **Support**: Check our [technical support page](/docs/documentation/resources/technical-support) # Swarms API MCP Server Source: https://docs.swarms.ai/docs/documentation/clients/swarms-api-mcp Connect any MCP-compatible agent to the Swarms API through the hosted remote MCP server at mcp.swarms.world. Run agents, orchestrate swarms, and process batches over a standard Streamable HTTP transport. The Swarms API MCP Server is a **hosted remote server** that exposes the entire Swarms API as Model Context Protocol tools. There is nothing to install and nothing to run locally — point your MCP client at one URL, send your API key as a header, and your agent can execute agents, orchestrate multi-agent swarms, run reasoning workflows, and process batches. **MCP Server URL:** `https://mcp.swarms.world/mcp` ## Overview | Property | Value | | --------------------- | ------------------------------------------------------ | | **URL** | `https://mcp.swarms.world/mcp` | | **Transport** | Streamable HTTP | | **Protocol version** | `2025-06-18` | | **Session handling** | Stateless — no `Mcp-Session-Id` to track | | **Authentication** | `x-api-key` header, supplied per request by the caller | | **Tools exposed** | 23 | | **Upstream base URL** | `https://api.swarms.world` | | **Installation** | None | ### Authentication The server holds **no API key of its own**. Every caller supplies their own key on the MCP request via the `x-api-key` header, and the server forwards it upstream. Your key is never passed as a tool argument, so it is never visible to the model driving the tools. Get a key from the [API Keys page](https://swarms.world/platform/api-keys). Calling a tool without a key returns a normal MCP error result rather than a transport failure: ``` This server requires callers to supply their own credentials. Send x-api-key with your MCP request. ``` `tools/list` works without a key, so agents can discover the tool surface before you authenticate. Only `tools/call` requires credentials. ## Setup by Client ### Claude Code ```bash theme={null} claude mcp add --transport http swarms https://mcp.swarms.world/mcp \ --header "x-api-key: your_api_key_here" ``` ### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS): ```json theme={null} { "mcpServers": { "swarms": { "url": "https://mcp.swarms.world/mcp", "headers": { "x-api-key": "your_api_key_here" } } } } ``` ### Cursor Add to **Cursor Settings → MCP**, or to your project-level `.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "swarms": { "url": "https://mcp.swarms.world/mcp", "headers": { "x-api-key": "your_api_key_here" } } } } ``` ### Windsurf, Codex, and other MCP clients Any client that supports remote MCP servers over Streamable HTTP works with the same two values — the URL and the `x-api-key` header. ```json theme={null} { "mcpServers": { "swarms": { "url": "https://mcp.swarms.world/mcp", "headers": { "x-api-key": "your_api_key_here" } } } } ``` ## Available Tools Tool names mirror the underlying API operation IDs, so a tool maps one-to-one onto an endpoint you can find in the [API Reference](https://docs.swarms.ai/api-reference). ### Agents | Tool | Endpoint | Purpose | | ------------------------------------------------- | ---------------------------------- | ------------------------------------------ | | `run_agent_v1_agent_completions_post` | `POST /v1/agent/completions` | Execute a single agent completion | | `run_agent_batch_v1_agent_batch_completions_post` | `POST /v1/agent/batch/completions` | Execute many agent completions in parallel | | `list_agents_v1_agents_list_get` | `GET /v1/agents/list` | List available agent configurations | ### Swarms | Tool | Endpoint | Purpose | | ------------------------------------------------------- | ---------------------------------- | ---------------------------------- | | `run_swarm_v1_swarm_completions_post` | `POST /v1/swarm/completions` | Execute a multi-agent swarm | | `run_batch_completions_v1_swarm_batch_completions_post` | `POST /v1/swarm/batch/completions` | Execute many swarms in parallel | | `check_swarm_types_v1_swarms_available_get` | `GET /v1/swarms/available` | List available swarm architectures | ### Specialized Workflows | Tool | Endpoint | Purpose | | ------------------------------------------------------------------ | -------------------------------------------- | ----------------------------------------- | | `run_graph_workflow_v1_graph_workflow_completions_post` | `POST /v1/graph-workflow/completions` | Execute a graph-based workflow | | `run_batched_grid_workflow_v1_batched_grid_workflow_comple_0dda3b` | `POST /v1/batched-grid-workflow/completions` | Execute a batched grid workflow | | `run_auto_agent_builder_v1_auto_agent_builder_completions_post` | `POST /v1/auto-agent-builder/completions` | Generate agent configurations from a task | | `run_reasoning_agent_completions_v1_reasoning_agent_comple_a8b363` | `POST /v1/reasoning-agent/completions` | Execute a reasoning agent completion | | `get_reasoning_agent_types_v1_reasoning_agent_types_get` | `GET /v1/reasoning-agent/types` | List reasoning agent types | ### Models and Tools | Tool | Endpoint | Purpose | | ---------------------------------------------- | --------------------------- | ------------------------------------- | | `get_available_models_v1_models_available_get` | `GET /v1/models/available` | List available AI models | | `list_models_v1_models_get` | `GET /v1/models` | List models (OpenAI-compatible shape) | | `chat_completions_v1_chat_completions_post` | `POST /v1/chat/completions` | OpenAI-compatible chat completions | | `get_available_tools_v1_tools_available_get` | `GET /v1/tools/available` | List available API tools | ### Account and Monitoring | Tool | Endpoint | Purpose | | ---------------------------------------------------- | ----------------------------------- | ----------------------------- | | `get_rate_limits_v1_rate_limits_get` | `GET /v1/rate/limits` | Rate limits and current usage | | `credit_balance_v1_account_credits_get` | `GET /v1/account/credits` | Credit balance | | `usage_costs_v1_usage_costs_get` | `GET /v1/usage/costs` | Comprehensive pricing details | | `get_metrics_summary_v1_account_metrics_summary_get` | `GET /v1/account/metrics/summary` | User metrics summary | | `get_logs_v1_account_logs_get` | `GET /v1/account/logs` | API request logs | | `premium_endpoints_v1_account_premium_endpoints_get` | `GET /v1/account/premium-endpoints` | Premium endpoint availability | | `health_health_get` | `GET /health` | Health check | | `root_get` | `GET /` | API root | Two tool names are truncated with a hash suffix (`..._comple_a8b363`, `..._comple_0dda3b`). MCP caps tool-name length, so the server truncates and appends a stable hash to keep names unique. Copy them exactly as written. ## Reading a Tool Result Every tool call returns both representations of the upstream response: * **`structuredContent`** — the parsed JSON object. Use this. No string parsing. * **`content[0].text`** — a human-readable rendering: an HTTP status line, then the pretty-printed JSON body. ```json theme={null} { "content": [ { "type": "text", "text": "HTTP 200 OK — POST /v1/agent/completions\n{\n \"job_id\": \"agent-b0abf28…\",\n …\n}" } ], "structuredContent": { "job_id": "agent-b0abf28…", "success": true, "name": "research-agent", "outputs": [ { "role": "research-agent", "content": "…", "timestamp": "…" } ], "usage": { "input_tokens": 7, "output_tokens": 62, "total_tokens": 69, "total_cost": 0.001192 } }, "isError": false } ``` An upstream failure comes back as `isError: true` with the message in `content[0].text` — it is a tool-level error, not a transport exception, so your client will not throw. ## Core Tool Parameters ### `run_agent_v1_agent_completions_post` | Parameter | Type | Required | Description | | --------------- | --------------- | -------- | ----------------------------------- | | `agent_config` | object | **Yes** | The agent specification (see below) | | `task` | string | No | The task for the agent to complete | | `history` | object \| array | No | Prior tasks and responses | | `img` | string | No | A single base64-encoded image | | `imgs` | array of string | No | Multiple base64-encoded images | | `tools_enabled` | array of string | No | Tools the agent may use | Common `agent_config` fields: | Field | Type | Default | Description | | ----------------- | ------------------- | ----------------- | ------------------------------------------- | | `agent_name` | string | — | Identifies the agent's role | | `system_prompt` | string | — | Initial instruction shaping behavior | | `model_name` | string | `claude-sonnet-5` | Model to run | | `max_tokens` | integer | `16000` | Output token cap | | `max_loops` | integer \| `"auto"` | `1` | Iterations, 1–50 or `"auto"` | | `temperature` | number | provider default | Randomness, 0–2 | | `fallback_models` | array of string | — | Models tried in order if the primary errors | | `role` | string | `worker` | Role within a swarm | ### `run_swarm_v1_swarm_completions_post` | Parameter | Type | Required | Description | | ---------------- | -------------------- | -------- | ---------------------------------- | | `name` | string | No | Swarm identifier, max 100 chars | | `description` | string | No | What the swarm is for | | `agents` | array of agent specs | No | Participating agents, up to 2000 | | `swarm_type` | string | No | Architecture — see below | | `task` | string | No | The objective | | `tasks` | array of string | No | Multiple objectives | | `max_loops` | integer | `1` | Execution loops, up to 50 | | `rearrange_flow` | string | No | Task ordering for `AgentRearrange` | | `stream` | boolean | `false` | Stream output | Valid `swarm_type` values: `AgentRearrange`, `MixtureOfAgents`, `SequentialWorkflow`, `ConcurrentWorkflow`, `GroupChat`, `MultiAgentRouter`, `HierarchicalSwarm`, `MajorityVoting`, `CouncilAsAJudge`, `HeavySwarm`, `BatchedGridWorkflow`, `LLMCouncil`, `DebateWithJudge`, `RoundRobin`, `PlannerWorkerSwarm`, `auto` ## TypeScript Install the official MCP SDK: ```bash theme={null} npm install @modelcontextprotocol/sdk ``` ### Agent Completions ```typescript theme={null} import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const apiKey = process.env.SWARMS_API_KEY; if (!apiKey) throw new Error("set SWARMS_API_KEY"); // The credential is a transport header. No tool takes it as an argument. const transport = new StreamableHTTPClientTransport( new URL("https://mcp.swarms.world/mcp"), { requestInit: { headers: { "x-api-key": apiKey } } }, ); const client = new Client({ name: "swarms-client", version: "1.0.0" }); await client.connect(transport); const result = await client.callTool({ name: "run_agent_v1_agent_completions_post", arguments: { agent_config: { agent_name: "research-agent", description: "Analyzes technical topics and reports concisely.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }, task: "Explain the CAP theorem in three bullets.", }, }); if (result.isError) { throw new Error(result.content[0].text); } // structuredContent is the parsed upstream JSON — no string parsing needed. const payload = result.structuredContent as any; console.log(payload.outputs[0].content); console.log(`cost: $${payload.usage.total_cost}`); await client.close(); ``` ### Swarm Completions ```typescript theme={null} import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( new URL("https://mcp.swarms.world/mcp"), { requestInit: { headers: { "x-api-key": process.env.SWARMS_API_KEY! } } }, ); const client = new Client({ name: "swarms-client", version: "1.0.0" }); await client.connect(transport); const result = await client.callTool({ name: "run_swarm_v1_swarm_completions_post", arguments: { name: "market-analysis", description: "Research a market, then critique the research.", swarm_type: "SequentialWorkflow", task: "Analyze the market for autonomous delivery robots.", max_loops: 1, agents: [ { agent_name: "researcher", system_prompt: "Gather and summarize market facts.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }, { agent_name: "critic", system_prompt: "Challenge weak claims in the research above.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }, ], }, }); if (result.isError) { throw new Error(result.content[0].text); } const payload = result.structuredContent as any; for (const message of payload.output) { console.log(`--- ${message.role} ---`); console.log(message.content); } console.log(`agents: ${payload.number_of_agents}`); console.log(`elapsed: ${payload.execution_time}s`); await client.close(); ``` ### Discovering Tools ```typescript theme={null} const { tools } = await client.listTools(); for (const tool of tools) { console.log(tool.name); } ``` ## Rust Add the official Rust MCP SDK to `Cargo.toml`: ```toml theme={null} [dependencies] rmcp = { version = "3.1", features = [ "client", "reqwest", "transport-streamable-http-client-reqwest", ] } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } serde_json = "1" ``` ### Agent Completions ```rust theme={null} use std::collections::HashMap; use rmcp::model::CallToolRequestParams; use rmcp::transport::{ streamable_http_client::StreamableHttpClientTransportConfig, StreamableHttpClientTransport, }; use rmcp::ServiceExt; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let api_key = std::env::var("SWARMS_API_KEY")?; // The credential is a transport header. No tool takes it as an argument. let mut headers = HashMap::new(); headers.insert("x-api-key".parse()?, api_key.parse()?); let transport = StreamableHttpClientTransport::from_config( StreamableHttpClientTransportConfig::with_uri("https://mcp.swarms.world/mcp") .custom_headers(headers), ); let client = ().serve(transport).await?; let result = client .call_tool( CallToolRequestParams::new("run_agent_v1_agent_completions_post").with_arguments( json!({ "agent_config": { "agent_name": "research-agent", "description": "Analyzes technical topics and reports concisely.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, "task": "Explain the CAP theorem in three bullets." }) .as_object() .cloned() .unwrap(), ), ) .await?; if result.is_error.unwrap_or(false) { return Err(format!("{:?}", result.content).into()); } // structured_content is the parsed upstream JSON — no string parsing needed. let payload = result.structured_content.ok_or("no structured content")?; println!("{}", payload["outputs"][0]["content"]); println!("cost: ${}", payload["usage"]["total_cost"]); client.cancel().await?; Ok(()) } ``` ### Swarm Completions ```rust theme={null} use std::collections::HashMap; use rmcp::model::CallToolRequestParams; use rmcp::transport::{ streamable_http_client::StreamableHttpClientTransportConfig, StreamableHttpClientTransport, }; use rmcp::ServiceExt; use serde_json::json; #[tokio::main] async fn main() -> Result<(), Box> { let api_key = std::env::var("SWARMS_API_KEY")?; let mut headers = HashMap::new(); headers.insert("x-api-key".parse()?, api_key.parse()?); let transport = StreamableHttpClientTransport::from_config( StreamableHttpClientTransportConfig::with_uri("https://mcp.swarms.world/mcp") .custom_headers(headers), ); let client = ().serve(transport).await?; let result = client .call_tool( CallToolRequestParams::new("run_swarm_v1_swarm_completions_post").with_arguments( json!({ "name": "market-analysis", "description": "Research a market, then critique the research.", "swarm_type": "SequentialWorkflow", "task": "Analyze the market for autonomous delivery robots.", "max_loops": 1, "agents": [ { "agent_name": "researcher", "system_prompt": "Gather and summarize market facts.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, { "agent_name": "critic", "system_prompt": "Challenge weak claims in the research above.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 } ] }) .as_object() .cloned() .unwrap(), ), ) .await?; if result.is_error.unwrap_or(false) { return Err(format!("{:?}", result.content).into()); } let payload = result.structured_content.ok_or("no structured content")?; for message in payload["output"].as_array().unwrap() { println!("--- {} ---", message["role"].as_str().unwrap_or("?")); println!("{}", message["content"].as_str().unwrap_or("")); } println!("agents: {}", payload["number_of_agents"]); println!("elapsed: {}s", payload["execution_time"]); client.cancel().await?; Ok(()) } ``` ### Discovering Tools ```rust theme={null} let tools = client.list_tools(Default::default()).await?; for tool in tools.tools { println!("{}", tool.name); } ``` ## Python The [official Python SDK](https://github.com/modelcontextprotocol/python-sdk) follows the same shape: ```bash theme={null} pip install mcp ``` ```python theme={null} import asyncio import os import httpx from mcp import ClientSession from mcp.client.streamable_http import streamable_http_client SERVER = "https://mcp.swarms.world/mcp" async def main() -> None: api_key = os.environ["SWARMS_API_KEY"] async with ( httpx.AsyncClient( headers={"x-api-key": api_key}, timeout=180 ) as http_client, streamable_http_client( SERVER, http_client=http_client ) as (read, write), ClientSession(read, write) as session, ): await session.initialize() result = await session.call_tool( "run_agent_v1_agent_completions_post", { "agent_config": { "agent_name": "research-agent", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000, }, "task": "Explain the CAP theorem in three bullets.", }, ) if result.is_error: raise RuntimeError(result.content[0].text) payload = result.structured_content print(payload["outputs"][0]["content"]) if __name__ == "__main__": asyncio.run(main()) ``` ## Verifying the Connection with curl The server speaks plain JSON-RPC over HTTP POST, so you can exercise it without any SDK: ```bash theme={null} curl -sS -X POST https://mcp.swarms.world/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "x-api-key: $SWARMS_API_KEY" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_available_models_v1_models_available_get", "arguments": {} } }' ``` Responses come back as a single SSE `data:` frame. Because the server is stateless, there is no session to establish first and no `Mcp-Session-Id` to echo back. ## Error Handling | Scenario | How it surfaces | What to do | | -------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------- | | Missing or invalid API key | `isError: true`, message names the `x-api-key` header | Set the header on the transport, not in tool arguments | | Rate limit exceeded | `isError: true` with the upstream 429 status line | Back off; check `get_rate_limits_v1_rate_limits_get` | | Invalid parameters | `isError: true` with the upstream 422 body | Compare against the tool's `inputSchema` from `tools/list` | | Insufficient credits | `isError: true` with the upstream error | Check `credit_balance_v1_account_credits_get` | | Long-running swarm | Client-side timeout | Raise the client's request timeout — large swarms can run for minutes | Because failures arrive as `isError: true` rather than thrown exceptions, always check that flag before reading `structuredContent`. ## Best Practices | Practice | Why | | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | Read `structuredContent`, not `content[0].text` | The text block is a rendering with a status-line prefix; the structured block is already parsed | | Keep the key in the transport header | It stays out of tool arguments, so the model never sees it | | Check `isError` before reading results | Upstream failures are tool-level results, not exceptions | | Raise client timeouts for swarms | Multi-agent runs routinely exceed default HTTP timeouts | | Cache `get_available_models_v1_models_available_get` | The model list changes rarely | | Prefer batch tools for bulk work | One call with many tasks beats many calls | | Watch `usage.total_cost` in responses | Every completion reports its own cost | ## Alternative: Local stdio Server If you need to run the bridge yourself — for network-isolated environments or custom tool filtering — the `swarms-ts-mcp` npm package runs a local stdio MCP server against the same API. ```json theme={null} { "mcpServers": { "swarms": { "command": "npx", "args": ["-y", "swarms-ts-mcp@latest", "--client=claude", "--tools=all"], "env": { "SWARMS_API_KEY": "your_api_key_here" } } } } ``` The local package exposes a different, smaller tool set with different tool names (`run_agent`, `run_swarms`, and so on) than the hosted server documented above. Code written against one will not run unchanged against the other. The hosted server at `mcp.swarms.world` is the recommended path. ## Resources | Resource | Link | | -------------------------- | ------------------------------------------------------------------------------------ | | **MCP Server URL** | `https://mcp.swarms.world/mcp` | | **Get an API key** | [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) | | **API Reference** | [docs.swarms.ai/api-reference](https://docs.swarms.ai/api-reference) | | **Docs MCP Server** | [Docs MCP and LLMs txt](/docs/documentation/clients/swarms-docs-mcp) | | **Model Context Protocol** | [modelcontextprotocol.io](https://modelcontextprotocol.io) | | **TypeScript SDK** | [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk) | | **Rust SDK** | [rmcp on crates.io](https://crates.io/crates/rmcp) | | **Python SDK** | [mcp on PyPI](https://pypi.org/project/mcp/) | | **Support** | [Discord](https://discord.gg/EamjgSaEQf) | # Docs MCP and LLMs txt Source: https://docs.swarms.ai/docs/documentation/clients/swarms-docs-mcp Give any coding agent Claude Code, Cursor, Codex, Windsurf, and more instant access to the Swarms API documentation via MCP or llms.txt. Stop copy-pasting docs. If you're vibe coding in Cursor, automating with Claude Code, or building an agent pipeline with Codex, you can give your agent instant, accurate access to the entire Swarms API either through a live MCP server it can query on-demand, or a single `llms.txt` file you drop into context. Both are free, require no API key, and take under a minute to set up. ## Overview Two ways to give your coding agent full access to the Swarms API documentation: | Method | Best For | URL | | -------------- | ------------------------------------------------------------- | --------------------------------- | | **MCP Server** | Agents with MCP support (Claude Code, Cursor, Windsurf, etc.) | `https://docs.swarms.ai/mcp` | | **llms.txt** | Paste-and-go context for any LLM or vibe coding session | `https://docs.swarms.ai/llms.txt` | No API key required for either. No installation needed. *** ## Option 1: MCP Server (Recommended for Agents) The Swarms Documentation MCP Server is a hosted remote server that exposes the entire Swarms API documentation as a live searchable tool. Connect it once and your agent can look up API references, code examples, and architecture guides on-demand. **MCP Server URL:** `https://docs.swarms.ai/mcp` ### Available Tool: `SearchSwarmsApiDocumentation` | Field | Value | | ---------------- | ----------------------- | | **Operation ID** | `MintlifyDefaultSearch` | | **Transport** | HTTP | ```json theme={null} { "type": "object", "properties": { "query": { "type": "string", "description": "A query to search the content with." } }, "required": ["query"] } ``` **Example queries your agent will run:** * `"agent completion API parameters"` * `"how to run a sequential workflow"` * `"mixture of agents example Python"` * `"authentication and API key setup"` * `"batch processing multiple agents"` ### Setup by Agent #### Claude Code ```bash theme={null} claude mcp add --transport http swarms-docs https://docs.swarms.ai/mcp ``` Or add manually to your MCP config: ```json theme={null} { "mcpServers": { "swarms-docs": { "url": "https://docs.swarms.ai/mcp" } } } ``` #### Claude Desktop Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS): ```json theme={null} { "mcpServers": { "swarms-docs": { "url": "https://docs.swarms.ai/mcp" } } } ``` #### Cursor Add to **Cursor Settings → MCP**, or to your project-level `.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "swarms-docs": { "url": "https://docs.swarms.ai/mcp" } } } ``` #### Windsurf Open the MCP configuration panel and add: ```json theme={null} { "mcpServers": { "swarms-docs": { "url": "https://docs.swarms.ai/mcp" } } } ``` #### OpenAI Codex / Agents SDK ```python theme={null} from agents import Agent, Runner from agents.mcp import MCPServerHTTP swarms_docs = MCPServerHTTP(url="https://docs.swarms.ai/mcp") agent = Agent( name="swarms-developer", instructions="You are an expert Swarms API developer. Use the Swarms documentation tool to look up accurate API details before writing code.", mcp_servers=[swarms_docs], ) ``` #### VS Code (GitHub Copilot) Add to your workspace `.vscode/settings.json`: ```json theme={null} { "mcp": { "servers": { "swarms-docs": { "type": "http", "url": "https://docs.swarms.ai/mcp" } } } } ``` #### Continue.dev Add to `~/.continue/config.json`: ```json theme={null} { "experimental": { "modelContextProtocolServers": [ { "transport": { "type": "http", "url": "https://docs.swarms.ai/mcp" } } ] } } ``` #### Any MCP-Compatible Agent Point any agent or framework that supports remote MCP HTTP transport at: ``` https://docs.swarms.ai/mcp ``` No authentication. No API key. Just works. *** ## Option 2: llms.txt (For Vibe Coders) `llms.txt` is a plain-text file containing the full Swarms API documentation in a format optimized for LLMs. Drop it into your context window, paste it into your system prompt, or use it as a reference file in any AI-assisted coding workflow. **URL:** `https://docs.swarms.ai/llms.txt` ### When to Use llms.txt Use `llms.txt` when: * You're in a **one-shot vibe coding session** and want to paste docs directly into the prompt * Your agent or IDE **doesn't support MCP** yet * You want to **seed a new conversation** with full API knowledge before asking your agent to write Swarms code * You're using a **raw API call** (OpenAI, Anthropic, Groq, etc.) and want docs in the system prompt ### How to Use It **In a system prompt:** ``` Fetch https://docs.swarms.ai/llms.txt and use it as your reference for all Swarms API code you write. ``` **In Claude / ChatGPT / Gemini:** 1. Open `https://docs.swarms.ai/llms.txt` in your browser 2. Copy the full content 3. Paste it at the top of your conversation or into the system prompt field 4. Start asking questions and generating Swarms code with full doc context **In Cursor / Windsurf (as a context file):** ``` @https://docs.swarms.ai/llms.txt ``` Add this reference at the top of your chat message. The agent will fetch and use the full docs as context. **Via curl (download locally):** ```bash theme={null} curl -o swarms-llms.txt https://docs.swarms.ai/llms.txt ``` Then reference the local file in your IDE or agent config. *** ## MCP Server Specification ```json theme={null} { "server": { "name": "Swarms API Documentation", "version": "1.0.0", "transport": "http" }, "capabilities": { "tools": { "SearchSwarmsApiDocumentation": { "name": "SearchSwarmsApiDocumentation", "description": "Search across the Swarms API Documentation knowledge base to find relevant information, code examples, API references, and guides.", "inputSchema": { "type": "object", "properties": { "query": { "type": "string", "description": "A query to search the content with." } }, "required": ["query"] }, "operationId": "MintlifyDefaultSearch" } } } } ``` *** ## Resources | Resource | Link | | -------------------------- | ------------------------------------------------------------------------ | | **MCP Server** | `https://docs.swarms.ai/mcp` | | **llms.txt** | `https://docs.swarms.ai/llms.txt` | | **Swarms API Docs** | [docs.swarms.ai](https://docs.swarms.ai) | | **Get API Key** | [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) | | **Model Context Protocol** | [modelcontextprotocol.io](https://modelcontextprotocol.io) | | **Discord Support** | [discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf) | # FAQ Source: https://docs.swarms.ai/docs/documentation/faq Get answers to the most common questions about the Swarms API platform, pricing, capabilities, and implementation. The Swarms API is a comprehensive platform for building and orchestrating AI agents and multi-agent systems. It enables developers to create individual intelligent agents or coordinate thousands of agents in complex workflows, allowing them to communicate, collaborate, and solve problems together. **Key Benefits:** * **Agent Orchestration**: Create and manage AI agents that can work independently or collaborate * **Multi-Agent Communication**: Enable agents to communicate and share information seamlessly * **Flexible Workflows**: Support for sequential, concurrent, hierarchical, and other workflow patterns * **Enterprise Scale**: Handle up to 10,000+ agents working together * **Multi-Model Support**: Integration with OpenAI, Anthropic, and Groq models The Swarms API is designed for developers who need more than just a simple AI completion endpoint. Here's why you should choose Swarms: * **Complete Agent Ecosystem**: Full ecosystem for building, deploying, and scaling intelligent AI systems * **Advanced Multi-Agent Architectures**: Build complex hierarchical, sequential, and parallel agent collaboration systems * **Agent-to-Agent Communication**: Advanced communication protocols enable seamless agent interaction * **Ultra-Optimized Runtime**: High-performance runtime with built-in optimization for concurrent operations * **Enterprise-Ready**: Built-in security, governance, and compliance features Agent orchestration in the Swarms API allows you to: * **Create Individual Agents**: Deploy single agents for specific tasks * **Coordinate Multiple Agents**: Build swarms where agents work together * **Define Workflow Patterns**: Choose from sequential, concurrent, hierarchical, and other patterns * **Enable Communication**: Agents can share information and collaborate * **Scale Dynamically**: Add or remove agents based on workload **Example Use Cases:** * Research teams with multiple agents researching different aspects * Medical analysis with lab analyzer and clinical specialist working together * Financial analysis with market analyst and economic forecaster collaborating * Content creation with writer, editor, and fact-checker in sequence The Swarms API supports multiple workflow patterns: | Workflow Type | Description | Best For | | ---------------------- | ---------------------------------------------------------- | ---------------------------------------------- | | **Sequential** | Agents work in order, each building on the previous output | Step-by-step processes, analysis pipelines | | **Concurrent** | Agents work simultaneously on the same task | Parallel processing, multiple perspectives | | **Hierarchical** | Structured multi-level approach with clear authority | Complex decision-making, management structures | | **Multi-Agent Router** | Intelligent task distribution based on capabilities | Load balancing, specialized task routing | | **Mixture of Agents** | Diverse teams with specialized skills | Complex problems requiring multiple expertise | | **Majority Voting** | Consensus-based decision making | Verification, quality assurance | | **Agent Rearrange** | Dynamic agent reconfiguration | Adaptive systems, optimization | The Swarms API supports multiple AI model providers: **OpenAI Models:** * gpt-4: High-quality reasoning and complex task handling * gpt-4.1: Optimized version with improved performance * gpt-4.1-mini: Lightweight version for faster responses **Anthropic Models:** * claude-sonnet-4-20250514: Balanced performance and reasoning * claude-sonnet-5: Default model used when model\_name is omitted **Groq Models (premium tier only):** * groq/llama-3.3-70b-versatile: High-performance open-source model * groq/openai/gpt-oss-120b: Large open-weight reasoning model Note that some models are restricted to premium-tier accounts: all `groq/*` models, plus each provider's current top-tier frontier model (the `gpt-5.6` family, `claude-fable-5`, `claude-opus-5`/`claude-opus-4-8`, `gemini-3.1-pro`/`gemini-3.1-deep-think`, `xai/grok-4.5`). Mid-tier and small models — including `gpt-4.1` — remain available on the free tier. For the complete, up-to-date list of supported models, call `GET /v1/models` (or `GET /v1/models/available` for model metadata). The Swarms API uses a transparent, usage-based pricing model with unified pricing across all endpoints: **Unified Token Pricing:** * **Input Tokens**: \$6.50 per 1 million tokens (all endpoints) * **Output Tokens**: \$18.50 per 1 million tokens (all endpoints) | Item | Cost | Notes | | ----------------------- | --------------------- | ---------------------------------------------- | | **Base cost per agent** | \$0.01 per agent | Charged for each agent in swarms and workflows | | **Input tokens** | \$6.50 per 1M tokens | Unified pricing for all endpoints | | **Output tokens** | \$18.50 per 1M tokens | Unified pricing for all endpoints | | **MCP cost** | \$0.10 per call | Charged if an agent uses an MCP URL | | **Image cost** | \$0.25 per image | Charged for each image processed | | **Exa Search tool** | \$0.04 per search | Charged per search execution | | **Web Scraper tool** | \$0.15 per scrape | Charged per scrape execution | | **Night-time discount** | 50% off token costs | 8 PM - 6 AM PT (Swarm Completions only) | **Pricing applies to:** * Swarm Completions (with agent cost) * Agent Completions * Graph Workflow (with agent cost) * Batched Grid Workflow (with agent cost) **Special Features:** * **Night Time Discount**: 50% off token costs for Swarm Completions during 8 PM - 6 AM Pacific Time * **Frenzy Mode**: All requests are free during Black Friday (24 hours) For detailed pricing information, examples, and cost calculation formulas, see the Pricing page. Rate limits are tier-based to ensure fair usage: | Rate Limit Type | Free Tier | Premium Tier | Time Window | | ----------------------- | --------- | ------------ | ----------- | | **Requests per Minute** | 100 | 2,000 | 1 minute | | **Requests per Hour** | 350 | 10,000 | 1 hour | | **Requests per Day** | 1,200 | 100,000 | 24 hours | | **Tokens per Agent** | 200,000 | 2,000,000 | Per request | | **Prompt Length** | 200,000 | 2,000,000 | Per request | | **Batch Size** | 50 | 50 | Per request | The batch size limit of 50 applies to all tiers. **Premium Tier Benefits:** * 20x more requests per minute (2,000 vs 100) * 28x more requests per hour (10,000 vs 350) * 83x more requests per day (100,000 vs 1,200) * 10x more tokens per agent (2M vs 200K) **1. Get Your API Key** Visit [Swarms Platform](https://swarms.world/platform/api-keys) to get your free API key. **2. Install Client Libraries** ```bash theme={null} # Python pip install swarms-client # JavaScript/TypeScript npm install axios dotenv ``` **3. Make Your First API Call** ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) result = client.agent.run( agent_config={ "agent_name": "My First Agent", "system_prompt": "You are a helpful assistant.", "model_name": "gpt-4.1-mini", "max_tokens": 1000, "temperature": 0.7, }, task="Hello, world!" ) print(result) ``` **Built-in Tools:** * **Search Capabilities**: Web search integration for research tasks * **MCP Integration**: Model Context Protocol for enhanced interactions * **Custom Tools**: Define your own function tools for specific needs **MCP (Model Context Protocol) Integration:** * Connect to external data sources * Integrate with databases and APIs * Enable real-time data access for agents **Custom Tool Development:** Create specialized tools using OpenAPI-style function specifications for enhanced agent capabilities. **Common Issues and Solutions:** **Authentication Errors:** * Verify your API key is correct and active * Check that the `x-api-key` header is properly set (the `Authorization: Bearer ` header is also accepted) * Ensure your API key has the necessary permissions **Rate Limit Exceeded:** * Implement exponential backoff for failed requests * Monitor your API usage to stay within limits * Consider upgrading to Premium for higher limits **Timeout Issues:** * Increase request timeout values * Consider breaking complex tasks into smaller chunks * Use batch processing for multiple operations **Model Availability:** * Check if your requested model is currently available * Have fallback models configured * Monitor model status through the health endpoint **Enterprise Security:** * **API Key Authentication**: Secure authentication for all requests * **Rate Limiting**: Prevents abuse and ensures fair usage * **Data Encryption**: All data is encrypted in transit and at rest * **Access Controls**: Granular permissions and access management **Best Practices:** * Never commit API keys to version control * Use environment variables for all sensitive configuration * Implement proper access controls in production environments * Regularly rotate API keys **Community Resources:** * **Documentation**: [docs.swarms.ai](https://docs.swarms.ai/) * **Discord Community**: [Join Discord](https://discord.gg/EamjgSaEQf) * **Technical Blog**: [Medium](https://medium.com/@kyeg) **Professional Support:** * **Technical Support**: [Book Support Session](https://cal.com/swarms/swarms-technical-support) * **Enterprise Support**: Contact through the platform * **Onboarding Sessions**: [Book with Kye Gomez](https://cal.com/swarms/swarms-onboarding-session) **Stay Updated:** * **Twitter**: [@kyegomez](https://twitter.com/kyegomez) * **LinkedIn**: [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) * **YouTube**: [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) Yes! The Swarms API is designed for production use with: * **High Availability**: 99.9% uptime SLA * **Scalability**: Handle thousands of concurrent agents * **Enterprise Features**: Security, compliance, and governance * **Monitoring**: Comprehensive logging and analytics * **Support**: Professional support for production deployments **Production Best Practices:** * Implement proper error handling and retry logic * Monitor API usage and costs * Use appropriate rate limiting strategies * Test thoroughly before deployment * Keep API keys secure and rotate regularly **Single Agents:** * **Purpose**: Focused tasks that don't require collaboration * **Use Cases**: Simple Q\&A, content generation, data analysis * **Benefits**: Fast, simple, cost-effective * **Limitations**: Limited to single perspective, no collaboration **Multi-Agent Swarms:** * **Purpose**: Complex tasks requiring multiple perspectives or specialized skills * **Use Cases**: Research teams, medical analysis, financial forecasting * **Benefits**: Multiple perspectives, specialized expertise, parallel processing * **Complexity**: Higher setup and coordination requirements **Model Selection Guidelines:** **For Complex Analysis:** * Use GPT-4 or Claude Sonnet 4 for tasks requiring deep reasoning * Higher token limits for comprehensive analysis **For Fast Responses:** * Choose gpt-4.1-mini for quick, straightforward tasks * Lower costs for high-volume applications **For Creative Tasks:** * Higher temperature settings (0.7-0.9) work better * GPT-4 or Claude models for creative content **For Factual Tasks:** * Lower temperature settings (0.1-0.3) provide more consistent responses * Any model can work well with proper prompting Yes! The Swarms API is designed for easy integration: **Integration Options:** * **REST API**: Standard HTTP endpoints for any language * **Client Libraries**: Official SDKs for Python, TypeScript, Go, Java * **Webhooks**: Real-time notifications for long-running tasks * **Batch Processing**: Process multiple requests efficiently **Common Integration Patterns:** * **Microservices**: Deploy as independent services * **API Gateway**: Integrate with existing API infrastructure * **Event-Driven**: Trigger agents based on system events * **Scheduled Tasks**: Run agents on regular schedules *** ## Still Have Questions? If you don't see your question answered here, we're here to help: * **Join our Discord**: [discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf) * **Book Technical Support**: [cal.com/swarms/swarms-technical-support](https://cal.com/swarms/swarms-technical-support) *Built with dedication by [The Swarm Corporation](https://swarms.ai)* # API Key Setup Source: https://docs.swarms.ai/docs/documentation/getting-started/api-key-setup This guide provides step-by-step instructions for obtaining and configuring your Swarms API key to access the Swarms platform services. This guide provides step-by-step instructions for obtaining and configuring your Swarms API key to access the Swarms platform services. ### Getting Started #### Step 1: Create Your Account 1. Navigate to the official Swarms platform: [https://swarms.world](https://swarms.world/) 2. Complete the registration process by providing the required information 3. Verify your email address to activate your account **Benefit**: New users automatically receive \$20 in free API credits upon successful signup. #### Step 2: Generate Your API Key 1. Log into your Swarms account 2. Access the API Keys section: [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 3. Click "Create New API Key" 4. Assign a descriptive name for your key (recommended for organization) 5. Configure key permissions based on your intended use case 6. Save the generated API key immediately **Important**: Store your API key securely as it will only be displayed once upon creation. #### Step 3: Environment Configuration Immediately after generating your API key, configure it in your environment: **Option A: Environment Variable (Recommended)** ```bash theme={null} export SWARMS_API_KEY="your_api_key_here" ``` **Option B: Environment File (.env)** ``` SWARMS_API_KEY=your_api_key_here ``` **Security Note**: Never commit API keys to version control systems. Use environment variables or secure configuration management tools. #### Step 4: Verify Your API Key Send your key in the `x-api-key` header. The `Authorization: Bearer ` header is also accepted (useful for OpenAI SDK compatibility). ```bash theme={null} curl -H "x-api-key: $SWARMS_API_KEY" https://api.swarms.world/v1/account/credits ``` ```bash theme={null} curl -H "Authorization: Bearer $SWARMS_API_KEY" https://api.swarms.world/v1/account/credits ``` A successful response returns your current credit balance, confirming the key is active. ### API Key Management #### Key Organization * Create specific API keys for different applications and services * Use descriptive naming conventions to identify key purposes * Regularly rotate keys for enhanced security * Monitor key usage through the platform dashboard #### Best Practices * Store keys in secure environment variables * Implement key rotation schedules * Monitor API usage and billing * Revoke unused or compromised keys immediately ### Credit System #### Initial Credits * **\$20 free credits** provided upon account creation * Credits applied automatically to your account balance * No payment information required for initial usage ### Support and Resources For technical support or billing inquiries: * Visit the Swarms platform documentation * Contact support through the platform dashboard * Check the community forums for common solutions ### Security Considerations * Keep API keys confidential and secure * Use HTTPS for all API communications * Implement proper error handling in applications * Monitor API usage for unusual activity * Report suspected security issues immediately *** # API Architecture Source: https://docs.swarms.ai/docs/documentation/getting-started/architecture The Swarms API provides a comprehensive multi-tier architecture for building collaborative agentic systems. The Swarms API provides a comprehensive multi-tier architecture for building intelligent AI systems. The platform is designed around three distinct agent paradigms, each optimized for different types of tasks and complexity levels. ### Architecture Tiers | Tier | Name | Agent Count | Complexity | Primary Use | Example Use Cases | API Endpoint | | ---------- | ------------------ | -------------- | ----------- | -------------------- | ------------------------------------------------- | --------------------------------- | | **Tier 1** | Individual Agents | 1 | Low-Medium | Focused tasks | Content generation, data analysis, Q\&A | `/v1/agent/completions` | | **Tier 2** | Reasoning Agents | 1-2 (internal) | Medium-High | Complex reasoning | Mathematical proofs, logical validation, research | `/v1/reasoning-agent/completions` | | **Tier 3** | Multi-Agent Swarms | 3-10,000+ | High | Enterprise workflows | Process automation, large-scale systems, R\&D | `/v1/swarm/completions` | #### Tier 1: Individual Agents **Single-purpose AI agents for focused tasks** Individual agents are the foundation of the Swarms ecosystem. These are custom-built, single-purpose AI agents designed to handle specific tasks with high precision and efficiency. **Key Characteristics** * **Single Agent**: One AI model per agent * **Focused Purpose**: Specialized for specific tasks * **Customizable**: Full control over system prompts, tools, and behavior * **Efficient**: Optimized for direct task execution * **Scalable**: Can be combined into larger systems **Use Cases** * Content generation (articles, code, reports) * Data analysis and processing * Customer service responses * Creative tasks (writing, design) * Simple Q\&A and information retrieval * Tool execution and automation **Example Implementation** ```python theme={null} import requests payload = { "agent_config": { "agent_name": "content-writer", "description": "Professional content writer for technical articles", "system_prompt": "You are an expert technical writer...", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.7 }, "task": "Write a comprehensive guide on API security best practices" } response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` #### Tier 2: Reasoning Agents **Advanced reasoning systems for complex problem-solving** **Premium Tier Required**: The `/v1/reasoning-agent/completions` endpoint is available only on Pro, Ultra, and Premium plans. [Upgrade your account](https://swarms.world/platform/account) to access advanced reasoning capabilities. Reasoning agents leverage sophisticated reasoning techniques to solve complex problems that require deep analysis, multiple perspectives, and systematic thinking. These agents may internally use 1-2 specialized sub-agents to achieve their reasoning goals. **Key Characteristics** * **Reasoning-Focused**: Built for complex logical and analytical tasks * **Multi-Perspective**: Can approach problems from different angles * **Iterative**: Capable of refinement and improvement cycles * **Specialized Types**: 9 different reasoning agent types available * **Internal Coordination**: May use sub-agents for specialized reasoning **Available Reasoning Agent Types** | Agent Type | Description | Best For | | --------------------- | ----------------------------------------------- | ---------------------------------------------- | | **reasoning-duo** | Dual-agent system with perspective synthesis | Mathematical problems, logical proofs | | **self-consistency** | Multiple reasoning paths with validation | Complex logical problems, consistency checking | | **ire** | Iterative refinement approach | Complex analysis, research problems | | **ire-agent** | Iterative refinement approach (agent variant) | Complex analysis, research problems | | **reasoning-agent** | General-purpose systematic reasoning | Step-by-step problem solving | | **consistency-agent** | Logical consistency and contradiction detection | Argument validation | | **ReflexionAgent** | Self-reflection and bias detection | Meta-cognitive tasks | | **GKPAgent** | Cross-domain knowledge synthesis | Interdisciplinary problems | | **AgentJudge** | Evaluates and judges agent outputs | Quality assessment, evaluation tasks | **Use Cases** * Mathematical proofs and complex calculations * Logical consistency validation * Research and analysis tasks * Cross-domain problem solving * Bias detection and ethical analysis * Iterative improvement scenarios **Example Implementation** ```python theme={null} payload = { "agent_name": "math-reasoner", "description": "Mathematical problem solver using dual perspectives", "model_name": "claude-sonnet-4-20250514", "system_prompt": "You are an expert mathematical reasoning agent...", "max_loops": 1, "swarm_type": "reasoning-duo", "task": "Prove that the sum of any three consecutive integers is divisible by 3" } response = requests.post( "https://api.swarms.world/v1/reasoning-agent/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` #### Tier 3: Multi-Agent Swarms **Large-scale agent systems for complex workflows** Multi-agent swarms represent the most sophisticated tier, capable of orchestrating anywhere from 3 to 10,000+ agents working together in coordinated workflows. These systems are designed for enterprise-scale applications and complex business processes. **Key Characteristics** * **Massive Scale**: 3 to 10,000+ agents per swarm * **Coordinated Workflows**: Agents work together in structured processes * **Multiple Swarm Types**: 16+ different swarm architectures available * **Enterprise-Grade**: Built for complex business applications * **Dynamic Routing**: Intelligent task distribution and agent selection **Available Swarm Types** | Swarm Type | Description | Agent Count | Best For | | ----------------------- | -------------------------------------- | ----------- | ------------------------------------------------ | | **SequentialWorkflow** | Linear task progression | 3-50 | Process automation, step-by-step workflows | | **ConcurrentWorkflow** | Parallel task execution | 5-100 | Parallel processing, independent tasks | | **GroupChat** | Interactive agent discussions | 3-20 | Collaborative problem solving, brainstorming | | **MixtureOfAgents** | Specialized agent selection | 5-200 | Complex tasks requiring multiple expertise areas | | **MajorityVoting** | Consensus-based decision making | 5-50 | Decision making, validation tasks | | **CouncilAsAJudge** | Expert panel with final judge | 5-30 | Expert evaluation, quality assessment | | **AgentRearrange** | Dynamic agent reordering | 3-100 | Adaptive workflows, optimization | | **MultiAgentRouter** | Intelligent task routing | 10-500 | Large-scale task distribution | | **HierarchicalSwarm** | Nested agent hierarchies | 10-1000 | Complex organizational structures | | **HeavySwarm** | Question, worker, and synthesis agents | 3-10 | Deep research, comprehensive analysis | | **LLMCouncil** | Council of models with a chairman | 3-10 | Multi-model deliberation, synthesis | | **DebateWithJudge** | Structured debate with a judge | 3-5 | Argument evaluation, contested questions | | **RoundRobin** | Agents take turns in rotation | 3-20 | Balanced participation, iterative refinement | | **PlannerWorkerSwarm** | Planner delegates to workers | 3-50 | Task decomposition, project execution | | **BatchedGridWorkflow** | Grid of tasks across agents | 2-100 | Running many task/agent combinations | | **auto** | Automatically selects a swarm type | Dynamic | Letting the API pick the best architecture | **Use Cases** * Enterprise process automation * Large-scale data processing * Complex decision-making systems * Research and development workflows * Customer service automation * Content creation pipelines * Quality assurance systems * Dynamic resource allocation **Example Implementation** ```python theme={null} payload = { "name": "Enterprise Content Pipeline", "description": "Multi-stage content creation and review system", "agents": [ { "agent_name": "researcher", "description": "Research and gather information", "model_name": "gpt-4.1", "role": "researcher" }, { "agent_name": "writer", "description": "Create initial content", "model_name": "claude-sonnet-4-20250514", "role": "writer" }, { "agent_name": "editor", "description": "Review and improve content", "model_name": "gpt-4.1", "role": "editor" }, { "agent_name": "fact-checker", "description": "Verify accuracy and sources", "model_name": "claude-sonnet-4-20250514", "role": "validator" } ], "max_loops": 1, "swarm_type": "SequentialWorkflow", "task": "Create a comprehensive industry report on AI trends in 2024" } response = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": "your-api-key"}, json=payload ) ``` ### Architecture Comparison | Aspect | Individual Agents | Reasoning Agents | Multi-Agent Swarms | | ------------------ | ----------------- | ----------------- | -------------------- | | **Agent Count** | 1 | 1-2 (internal) | 3-10,000+ | | **Complexity** | Low-Medium | Medium-High | High-Extreme | | **Use Case** | Focused tasks | Complex reasoning | Enterprise workflows | | **Setup Time** | Minutes | Minutes-Hours | Hours-Days | | **Resource Usage** | Low | Medium | High | | **Scalability** | Individual | Limited | Massive | | **Cost** | Low | Medium | High | | **Maintenance** | Simple | Moderate | Complex | ### Choosing the Right Architecture #### When to Use Individual Agents * ✅ Single, well-defined tasks * ✅ Quick prototyping and testing * ✅ Resource-constrained environments * ✅ Simple automation needs * ✅ Cost-sensitive applications #### When to Use Reasoning Agents * ✅ Complex problem-solving tasks * ✅ Tasks requiring multiple perspectives * ✅ Logical consistency validation * ✅ Research and analysis work * ✅ Tasks requiring iterative improvement #### When to Use Multi-Agent Swarms * ✅ Complex business processes * ✅ Large-scale automation * ✅ Multi-step workflows * ✅ Enterprise applications * ✅ Tasks requiring multiple expertise areas * ✅ Dynamic, adaptive systems ### Integration Patterns #### Hybrid Approaches You can combine different tiers for optimal results: 1. **Individual + Reasoning**: Use individual agents for data collection, reasoning agents for analysis 2. **Reasoning + Swarms**: Use reasoning agents within swarms for complex decision-making 3. **All Three Tiers**: Individual agents for data processing, reasoning agents for analysis, swarms for orchestration #### Migration Paths * **Start Simple**: Begin with individual agents, upgrade to reasoning agents for complex tasks * **Scale Up**: Move from reasoning agents to swarms for enterprise needs * **Optimize**: Use reasoning agents within swarms for enhanced decision-making ### Performance Considerations #### Individual Agents * **Latency**: 1-5 seconds * **Throughput**: High (1000+ requests/minute) * **Cost**: \$0.01-0.10 per request * **Memory**: Minimal #### Reasoning Agents * **Latency**: 5-30 seconds * **Throughput**: Medium (100-500 requests/minute) * **Cost**: \$0.05-0.50 per request * **Memory**: Moderate #### Multi-Agent Swarms * **Latency**: 30 seconds - 10 minutes * **Throughput**: Variable (10-100 requests/minute) * **Cost**: \$0.10-5.00 per request * **Memory**: High ### Best Practices #### 1. Start with the Right Tier * Begin with individual agents for simple tasks * Upgrade to reasoning agents when complexity increases * Use swarms only when necessary for scale #### 2. Optimize for Your Use Case * Match agent capabilities to task requirements * Consider cost vs. performance trade-offs * Plan for scalability from the start #### 3. Monitor and Iterate * Track performance metrics across all tiers * Optimize based on usage patterns * Consider hybrid approaches for complex needs ### Getting Started #### Quick Start Guide 1. **Get API Key**: [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. **Choose Your Tier**: Start with individual agents for simple tasks 3. **Build and Test**: Create your first agent and test functionality 4. **Scale Up**: Move to reasoning agents or swarms as needed ### Support and Community * **Technical Support**: [Book a Call](https://cal.com/swarms/swarms-technical-support) * **Community**: [Join our Discord](https://discord.gg/EamjgSaEQf) * **Updates**: [Follow us on Twitter](https://twitter.com/swarms_corp) For enterprise deployments and custom solutions, contact our team for dedicated support and consultation. # Quickstart Source: https://docs.swarms.ai/docs/documentation/getting-started/quickstart The Swarms API enables you to create and orchestrate AI agents for both single-agent tasks and multi-agent workflows. The Swarms API enables you to create and orchestrate AI agents for both single-agent tasks and multi-agent workflows. The platform supports various AI models and provides flexible orchestration patterns for complex problem-solving scenarios. #### Key Features * **Single Agent Operations**: Deploy individual AI agents for specific tasks * **Multi-Agent Swarms**: Coordinate multiple agents working together * **Sequential Workflows**: Agents work in ordered sequence, building on previous outputs * **Concurrent Workflows**: Agents work in parallel for faster processing * **Tools Integration**: Extend agent capabilities with custom functions * **Multiple Model Support**: Choose from OpenAI, Anthropic, and Groq models ### Getting Started #### Prerequisites Before you begin, ensure you have: * Python 3.7+ or Node.js for JavaScript/TypeScript * An API key from [Swarms Platform](https://swarms.world/platform/api-keys) * Required libraries installed #### Installation **Python:** ```bash theme={null} pip install requests python-dotenv ``` **JavaScript/TypeScript:** ```bash theme={null} npm install axios dotenv ``` #### Authentication The API uses API key authentication through the `x-api-key` header. For OpenAI SDK compatibility, the `Authorization: Bearer ` header is also accepted. Store your API key securely as an environment variable. **Base URL:** * Production: `https://api.swarms.world` **Security Note:** Never hardcode API keys in your code. Always use environment variables or secure configuration management. ### Single Agent Usage Single agents are ideal for focused tasks that don't require collaboration between multiple AI systems. #### Basic Health Check Before making API calls, verify your connection: **Python:** ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } response = requests.get(f"{BASE_URL}/health", headers=headers) print(response.json()) ``` **JavaScript/TypeScript:** ```javascript theme={null} import axios from 'axios'; import * as dotenv from 'dotenv'; dotenv.config(); const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = 'https://api.swarms.world'; const headers = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' }; const response = await axios.get(`${BASE_URL}/health`, { headers }); console.log(response.data); ``` #### Creating a Basic Agent A single agent requires an agent configuration and a task to execute: **Python:** ```python theme={null} def run_single_agent(): payload = { "agent_config": { "agent_name": "Research Analyst", "description": "An expert in analyzing and synthesizing research data", "system_prompt": ( "You are a Research Analyst with expertise in data analysis and synthesis. " "Your role is to analyze provided information, identify key insights, " "and present findings in a clear, structured format." ), "model_name": "claude-sonnet-4-20250514", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 1, "auto_generate_prompt": False, "tools_list_dictionary": None, }, "task": "What are the key trends in renewable energy adoption?", } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) return response.json() ``` **JavaScript/TypeScript:** ```javascript theme={null} async function runSingleAgent() { const payload = { agent_config: { agent_name: "Research Analyst", description: "An expert in analyzing and synthesizing research data", system_prompt: "You are a Research Analyst with expertise in data analysis and synthesis.", model_name: "claude-sonnet-4-20250514", role: "worker", max_loops: 1, max_tokens: 8192, temperature: 1, auto_generate_prompt: false, tools_list_dictionary: null }, task: "What are the key trends in renewable energy adoption?" }; const response = await axios.post( `${BASE_URL}/v1/agent/completions`, payload, { headers } ); return response.data; } ``` #### Agent Configuration Parameters * **agent\_name**: Descriptive name for your agent * **description**: Brief description of the agent's purpose * **system\_prompt**: Detailed instructions defining the agent's role and capabilities * **model\_name**: AI model to use (see supported models section) * **role**: Agent role, typically "worker" * **max\_loops**: Maximum number of processing loops * **max\_tokens**: Maximum response length * **temperature**: Response creativity (0.0 = deterministic, 1.0 = creative) * **auto\_generate\_prompt**: Whether to auto-enhance the system prompt * **tools\_list\_dictionary**: Optional tools for extended functionality #### Maintaining Conversation History For multi-turn conversations, include previous messages in the history parameter: **Python:** ```python theme={null} def run_agent_with_history(): payload = { "agent_config": { "agent_name": "Conversation Agent", "description": "An agent that maintains conversation context", "system_prompt": "You are a helpful assistant that maintains context.", "model_name": "claude-sonnet-4-20250514", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": False, }, "task": "What's the weather like?", "history": [ { "role": "user", "content": "I'm planning a trip to New York." }, { "role": "assistant", "content": "That's great! When are you planning to visit?" }, { "role": "user", "content": "Next week." } ] } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) return response.json() ``` ### Multi-Agent Swarms Multi-agent swarms enable complex problem-solving by coordinating multiple AI agents. Swarms support two primary workflow types: #### Workflow Types **Sequential Workflow:** Agents execute in order, with each agent building upon the previous agent's output. This is ideal for tasks requiring step-by-step processing. **Concurrent Workflow:** Agents work simultaneously on the same task, providing parallel processing for faster results and diverse perspectives. #### Sequential Workflow Example Sequential workflows are perfect for analysis pipelines where each step depends on the previous one: **Python:** ```python theme={null} def run_sequential_swarm(): payload = { "name": "Financial Analysis Swarm", "description": "Market analysis swarm", "agents": [ { "agent_name": "Market Analyst", "description": "Analyzes market trends", "system_prompt": "You are a financial analyst expert specializing in market trend analysis.", "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "auto_generate_prompt": False }, { "agent_name": "Economic Forecaster", "description": "Predicts economic trends", "system_prompt": "You are an expert in economic forecasting. Use the market analysis to provide economic predictions.", "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "auto_generate_prompt": False } ], "max_loops": 1, "swarm_type": "SequentialWorkflow", "task": "Analyze the current market conditions and provide economic forecasts." } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload ) return response.json() ``` #### Concurrent Workflow Example Concurrent workflows are ideal when you need multiple perspectives or parallel processing: **Python:** ```python theme={null} def run_concurrent_swarm(): payload = { "name": "Medical Analysis Swarm", "description": "Analyzes medical data concurrently", "agents": [ { "agent_name": "Lab Data Analyzer", "description": "Analyzes lab report data", "system_prompt": "You are a medical data analyst specializing in lab results interpretation.", "model_name": "claude-sonnet-4-20250514", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "auto_generate_prompt": False }, { "agent_name": "Clinical Specialist", "description": "Provides clinical interpretations", "system_prompt": "You are an expert in clinical diagnosis and patient care recommendations.", "model_name": "claude-sonnet-4-20250514", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "auto_generate_prompt": False } ], "max_loops": 1, "swarm_type": "ConcurrentWorkflow", "task": "Analyze these lab results and provide clinical interpretations." } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload ) return response.json() ``` #### Batch Processing **Premium Tier Required**: The `/v1/swarm/batch/completions` endpoint is restricted to Pro, Ultra, and Premium plan subscribers. [Upgrade your account](https://swarms.world/platform/account) to access batch swarm processing. Process multiple swarms in a single request for improved efficiency: **Python:** ```python theme={null} def run_batch_swarms(): payload = [ { "name": "Research Swarm", "description": "Conducts comprehensive research", "agents": [ { "agent_name": "Research Agent", "description": "Conducts initial research", "system_prompt": "You are a research assistant specializing in comprehensive data gathering.", "model_name": "gpt-4", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": False }, { "agent_name": "Analysis Agent", "description": "Analyzes research data", "system_prompt": "You are a data analyst who synthesizes research findings.", "model_name": "gpt-4", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": False } ], "max_loops": 1, "swarm_type": "SequentialWorkflow", "task": "Research recent AI advancements and provide analysis." } ] response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload ) return response.json() ``` ### Advanced Features #### Tools Integration Enhance agent capabilities by providing specialized tools. Tools are defined using OpenAPI-style function specifications: **Python:** ```python theme={null} def run_agent_with_tools(): tools_dictionary = [ { "type": "function", "function": { "name": "search_topic", "description": "Conduct an in-depth search on a specific topic", "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": "Search depth level (1-3, where 3 is most comprehensive)" }, "detailed_queries": { "type": "array", "description": "List of specific search queries to execute", "items": { "type": "string" } } }, "required": ["depth", "detailed_queries"] } } } ] payload = { "agent_config": { "agent_name": "Research Assistant", "description": "Expert researcher with advanced search capabilities", "system_prompt": "You are a research assistant with access to advanced search tools. Use the search_topic function when you need to gather comprehensive information.", "model_name": "gpt-4", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": False, "tools_list_dictionary": tools_dictionary }, "task": "Research the latest developments in quantum computing and provide a comprehensive analysis." } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) return response.json() ``` #### Tool Definition Guidelines When creating tools for your agents: 1. **Clear Names**: Use descriptive function names that clearly indicate the tool's purpose 2. **Detailed Descriptions**: Provide comprehensive descriptions of what the tool does 3. **Parameter Specifications**: Define all parameters with appropriate types and descriptions 4. **Required Fields**: Specify which parameters are mandatory 5. **Usage Context**: Include guidance in the system prompt about when to use specific tools ### Supported Models Choose the appropriate model based on your use case requirements: Some models are restricted to premium-tier accounts: all `groq/*` models, plus each provider's current top-tier frontier model (e.g. the `gpt-5.6` family, `claude-fable-5`, `claude-opus-5`/`claude-opus-4-8`, `gemini-3.1-pro`/`gemini-3.1-deep-think`, `grok-4.5`). Mid-tier and small models — including `gpt-4.1` — remain available on the free tier. Call `GET /v1/models/available` with your key for the authoritative, tier-aware list. #### OpenAI Models * **gpt-4**: High-quality reasoning and complex task handling * **gpt-4.1**: Optimized version with improved performance * **gpt-4.1-mini**: Lightweight version for faster responses #### Anthropic Models * **claude-sonnet-4-20250514**: Balanced performance and reasoning * **claude-sonnet-5**: Default model used when model\_name is omitted #### Groq Models (premium tier only) * **groq/llama-3.3-70b-versatile**: High-performance open-source model * **groq/openai/gpt-oss-120b**: Large open-weight reasoning model #### Model Selection Guidelines * **Complex Analysis**: Use GPT-4 or Claude Sonnet 4 for tasks requiring deep reasoning * **Fast Responses**: Choose gpt-4.1-mini for quick, straightforward tasks * **Creative Tasks**: Higher temperature settings work better with creative models * **Factual Tasks**: Lower temperature settings provide more consistent, factual responses ### API Reference #### Endpoints | Method | Endpoint | Description | | ------ | --------------------------------------- | ----------------------------------------- | | `GET` | `/health` | Health check | | `POST` | `/v1/agent/completions` | Single agent completions | | `POST` | `/v1/agent/batch/completions` | Batch agent completions (premium) | | `POST` | `/v1/swarm/completions` | Swarm completions | | `POST` | `/v1/swarm/batch/completions` | Batch swarm completions (premium) | | `POST` | `/v1/reasoning-agent/completions` | Reasoning agent completions (premium) | | `GET` | `/v1/reasoning-agent/types` | List available reasoning agent types | | `POST` | `/v1/chat/completions` | OpenAI-compatible chat completions | | `POST` | `/v1/batched-grid-workflow/completions` | Batched grid workflow (premium) | | `POST` | `/v1/graph-workflow/completions` | Graph workflow (premium) | | `POST` | `/v1/auto-agent-builder/completions` | Generate agent configurations from a task | | `GET` | `/v1/swarms/available` | List available swarm types | | `GET` | `/v1/models` | List supported models | | `GET` | `/v1/models/available` | List available models with metadata | | `GET` | `/v1/tools/available` | List available tools | | `GET` | `/v1/agents/list` | List your agents | | `GET` | `/v1/swarm/logs` | Retrieve your API request logs | | `GET` | `/v1/rate/limits` | View your rate limits and usage | | `GET` | `/v1/metrics/summary` | Usage metrics summary | | `GET` | `/v1/usage/costs` | Usage cost breakdown | | `GET` | `/v1/account/credits` | Check your credit balance | ### Best Practices #### Security * Never commit API keys to version control * Use environment variables for all sensitive configuration * Implement proper access controls in production environments * Regularly rotate API keys #### Error Handling Implement robust error handling for production applications: **Python:** ```python theme={null} import time from tenacity import retry, wait_exponential, stop_after_attempt @retry( wait=wait_exponential(multiplier=1, min=4, max=10), stop=stop_after_attempt(3) ) def make_api_call(payload): try: response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=30 ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"API call failed: {e}") raise def validate_payload(payload): required_fields = ["agent_config", "task"] if not all(field in payload for field in required_fields): raise ValueError("Missing required fields in payload") agent_config = payload["agent_config"] required_config_fields = ["agent_name", "system_prompt", "model_name"] if not all(field in agent_config for field in required_config_fields): raise ValueError("Missing required fields in agent_config") ``` #### Rate Limiting * Implement exponential backoff for failed requests * Monitor your API usage to stay within limits * Use batch processing when possible to reduce individual request volume #### Performance Optimization * Cache responses when appropriate * Use concurrent workflows for independent tasks * Choose the right model for your specific use case * Optimize token usage by being specific in your prompts #### Testing Strategy * Start with simple, single-agent tasks * Test with different models to find the best fit * Gradually increase complexity as you understand the system * Implement comprehensive logging for debugging ### Troubleshooting #### Common Issues **Authentication Errors:** * Verify your API key is correct and active * Check that the `x-api-key` header (or `Authorization: Bearer `) is properly set * Ensure your API key has the necessary permissions **Timeout Issues:** * Increase request timeout values * Consider breaking complex tasks into smaller chunks * Use batch processing for multiple operations **Model Availability:** * Check if your requested model is currently available * Have fallback models configured * Monitor model status through the health endpoint **Payload Validation:** * Ensure all required fields are present * Validate data types match the expected format * Check that tool definitions follow the correct schema ### Getting Help #### Community Resources * **Documentation**: [docs.swarms.ai](https://docs.swarms.ai/) * **Discord Community**: [Join Discord](https://discord.gg/EamjgSaEQf) * **Technical Blog**: [Medium](https://medium.com/@kyeg) #### Professional Support * **Onboarding Sessions**: [Book with Kye Gomez](https://cal.com/swarms/swarms-onboarding-session) * **Enterprise Support**: Contact through the platform #### Stay Updated * **Twitter**: [@kyegomez](https://twitter.com/kyegomez) * **LinkedIn**: [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) * **YouTube**: [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) * **Community Events**: [Sign up here](https://lu.ma/5p2jnc2v) ### Conclusion The Swarms API provides a powerful platform for building sophisticated AI agent systems. Whether you're working with single agents for focused tasks or orchestrating complex multi-agent workflows, the platform offers the flexibility and tools needed to create effective AI solutions. Start with simple implementations and gradually explore more advanced features like tools integration and multi-agent coordination. The community and documentation resources are available to help you succeed in building powerful agent-based applications. # Setup & Configuration Source: https://docs.swarms.ai/docs/documentation/getting-started/setup Complete setup guide for the Swarms API. Learn how to configure authentication, set up your development environment, and start building with our multi-agent swarm platform. | **Argument** | **Description** | **Value** | **Notes** | | ---------------------------- | --------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------- | | **Base URL / Domain** | The base URL or domain for the Swarms API | `https://api.swarms.world` | Production URL for all API requests | | **Headers: x-api-key** | API key header for authentication | `x-api-key: ` | Required for authenticating requests | | **Headers: Authorization** | Alternative authentication header | `Authorization: Bearer ` | Accepted as an alternative to `x-api-key` (OpenAI SDK compatibility) | | **Headers: Content-Type** | Specifies the media type of the request body | `application/json` | Indicates JSON payload for POST/PUT requests | | **Headers: Accept-Encoding** | Compression formats supported by the client | `gzip, lz4` | Client indicates it can handle gzip or lz4 compressed responses | | **Method** | HTTP methods supported | `GET`, `POST`, `PUT`, `DELETE`, etc. | Typical REST API methods; specific methods depend on endpoint | | **Request Body** | JSON payload for requests (for POST/PUT) | `{"key": "value"}` | Must conform to `application/json` content type | | **Response Format** | Expected response format | `application/json` | API returns JSON responses | | **Compression** | Compression algorithms supported for response | `gzip`, `lz4` | Server may compress responses if client supports it (via Accept-Encoding) | ### Notes: * **Base URL**: Use `https://api.swarms.world` for all API requests. * **API Key**: Replace `` with the actual key provided by the Swarms API service. * **Authentication**: Pass your key in the `x-api-key` header, or use `Authorization: Bearer ` — both are accepted. * **Compression**: `gzip` and `lz4` are supported for response compression via the `Accept-Encoding` header. # Welcome Source: https://docs.swarms.ai/docs/documentation/index The Swarms API is the most advanced platform for building multi-agent systems. If you're creating a single intelligent agent or orchestrating thousands of agents in complex workflows, Swarms provides the tools, infrastructure, and runtime you need to bring your agents into production. ## Platform Benefits Swarms API is designed for developers who need more than just a simple AI completion endpoint. We provide a complete ecosystem for building, deploying, and scaling intelligent AI systems that can collaborate, reason, and solve complex problems together. Build hierarchical, sequential, and parallel agent systems at scale (10,000+). Protocols enabling seamless coordination and knowledge sharing across agents. High-performance, concurrent runtime optimized for resource efficiency. Persistent, shareable memory for complex workflows and long-lived context. Test and validate swarms in controlled environments before production. Enterprise-grade security, governance, and reliability. ## Getting Started ### Essential Setup Create your API key and configure authentication. Build your first agent in under 5 minutes. Set up your development environment. ### Core Architecture Three-tier architecture for scalable AI operations. Official SDKs for Python, TypeScript, Go, Java, and more. Explore different swarm configurations and patterns. ### Workflow Patterns Chain agents for step-by-step processing. Run agents in parallel for maximum throughput. Build agent hierarchies for complex decision-making. Intelligent routing and load balancing. Combine specialist agents for better results. Consensus-based decision making. Dynamically reconfigure active agents. ## Advanced Capabilities Generate structured data with validation. Model Context Protocol for enhanced interactions. ## Resources & Support API usage limits and quotas. Transparent pricing structure. Join our developer community. Enterprise support and troubleshooting. Complete OpenAPI specification. Practical, runnable examples for agents, workflows, and utilities. ## Ready to Build? Join thousands of developers building the future of AI with Swarms API. Start with our comprehensive documentation, explore our examples, and join our community. Build your first agent in minutes. Explore the full API specification. Connect with developers and get help. *** *Built with dedication by [The Swarm Corporation](https://swarms.ai)* # AgentRearrange Source: https://docs.swarms.ai/docs/documentation/multi-agent/agent_rearrange Dynamic swarm architecture that can reorganize agent roles and responsibilities based on task requirements and performance **Swarm Type**: `AgentRearrange` ## Overview The AgentRearrange swarm type implements a dynamic architecture where agents can be reassigned to different roles and responsibilities based on task requirements, performance metrics, or changing circumstances. This flexibility allows the swarm to adapt to different scenarios and optimize performance through intelligent role reallocation. Key features: * **Dynamic Role Assignment**: Agents can switch roles based on task needs * **Performance-Based Reorganization**: Roles adjusted based on agent performance * **Adaptive Architecture**: Swarm structure evolves with changing requirements * **Flexible Resource Allocation**: Optimal use of agent capabilities ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> R["Researcher"] R --> W["Writer"] R --> E["Editor"] W --> O["Result"] E --> O ``` The shape comes from `rearrange_flow`. Above is `"Researcher -> Writer, Editor"`: `->` is a handoff to the next step, and a comma runs agents in parallel within the same step. ## Use Cases * Dynamic project management with changing requirements * Adaptive content creation workflows * Performance optimization in multi-agent systems * Flexible task allocation based on agent strengths ## API Usage The `AgentRearrange` swarm type **requires** the `rearrange_flow` parameter. It is a string that defines how tasks flow between agents by `agent_name`: use `->` for sequential handoffs and commas for agents that run in parallel within the same step (e.g. `"Researcher -> Writer, Editor"`). Requests without `rearrange_flow` are rejected with a `400` error. ### Basic AgentRearrange Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Adaptive Content Creation", "description": "Dynamic content creation with flexible agent role assignment", "swarm_type": "AgentRearrange", "rearrange_flow": "Research Specialist -> Technical Writer -> Finance Expert -> Editor", "task": "Create a comprehensive technical blog post about machine learning in finance, with the ability to reassign agent roles based on content needs", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts research and gathers information", "system_prompt": "You are a research specialist. Gather comprehensive information on machine learning applications in finance, including current trends, use cases, and future prospects.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Writer", "description": "Creates technical content and explanations", "system_prompt": "You are a technical writer specializing in machine learning and finance. Create clear, engaging technical content that explains complex concepts in accessible terms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Finance Expert", "description": "Provides financial domain expertise", "system_prompt": "You are a finance expert with knowledge of machine learning applications. Ensure accuracy in financial concepts, market analysis, and industry insights.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Editor", "description": "Reviews and polishes content", "system_prompt": "You are a professional editor. Review content for clarity, flow, accuracy, and overall quality. Make improvements while maintaining technical accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Adaptive Content Creation", "description": "Dynamic content creation with flexible agent role assignment", "swarm_type": "AgentRearrange", "rearrange_flow": "Research Specialist -> Technical Writer -> Finance Expert -> Editor", "task": "Create a comprehensive technical blog post about machine learning in finance, with the ability to reassign agent roles based on content needs", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts research and gathers information", "system_prompt": "You are a research specialist. Gather comprehensive information on machine learning applications in finance, including current trends, use cases, and future prospects.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Writer", "description": "Creates technical content and explanations", "system_prompt": "You are a technical writer specializing in machine learning and finance. Create clear, engaging technical content that explains complex concepts in accessible terms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Finance Expert", "description": "Provides financial domain expertise", "system_prompt": "You are a finance expert with knowledge of machine learning applications. Ensure accuracy in financial concepts, market analysis, and industry insights.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Editor", "description": "Reviews and polishes content", "system_prompt": "You are a professional editor. Review content for clarity, flow, accuracy, and overall quality. Make improvements while maintaining technical accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("AgentRearrange swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Dynamic results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Adaptive Content Creation", description: "Dynamic content creation with flexible agent role assignment", swarm_type: "AgentRearrange", rearrange_flow: "Research Specialist -> Technical Writer -> Finance Expert -> Editor", task: "Create a comprehensive technical blog post about machine learning in finance, with the ability to reassign agent roles based on content needs", agents: [ { agent_name: "Research Specialist", description: "Conducts research and gathers information", system_prompt: "You are a research specialist. Gather comprehensive information on machine learning applications in finance, including current trends, use cases, and future prospects.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Technical Writer", description: "Creates technical content and explanations", system_prompt: "You are a technical writer specializing in machine learning and finance. Create clear, engaging technical content that explains complex concepts in accessible terms.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.5 }, { agent_name: "Finance Expert", description: "Provides financial domain expertise", system_prompt: "You are a finance expert with knowledge of machine learning applications. Ensure accuracy in financial concepts, market analysis, and industry insights.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Editor", description: "Reviews and polishes content", system_prompt: "You are a professional editor. Review content for clarity, flow, accuracy, and overall quality. Make improvements while maintaining technical accuracy.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("AgentRearrange swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Dynamic results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` RearrangeFlow string `json:"rearrange_flow"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Adaptive Content Creation", Description: "Dynamic content creation with flexible agent role assignment", SwarmType: "AgentRearrange", RearrangeFlow: "Research Specialist -> Technical Writer -> Finance Expert -> Editor", Task: "Create a comprehensive technical blog post about machine learning in finance, with the ability to reassign agent roles based on content needs", Agents: []Agent{ { AgentName: "Research Specialist", Description: "Conducts research and gathers information", SystemPrompt: "You are a research specialist. Gather comprehensive information on machine learning applications in finance, including current trends, use cases, and future prospects.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Technical Writer", Description: "Creates technical content and explanations", SystemPrompt: "You are a technical writer specializing in machine learning and finance. Create clear, engaging technical content that explains complex concepts in accessible terms.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Finance Expert", Description: "Provides financial domain expertise", SystemPrompt: "You are a finance expert with knowledge of machine learning applications. Ensure accuracy in financial concepts, market analysis, and industry insights.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Editor", Description: "Reviews and polishes content", SystemPrompt: "You are a professional editor. Review content for clarity, flow, accuracy, and overall quality. Make improvements while maintaining technical accuracy.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Adaptive Content Creation", "description": "Dynamic content creation with flexible agent role assignment", "swarm_type": "AgentRearrange", "rearrange_flow": "Research Specialist -> Technical Writer -> Finance Expert -> Editor", "task": "Create a comprehensive technical blog post about machine learning in finance, with the ability to reassign agent roles based on content needs", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts research and gathers information", "system_prompt": "You are a research specialist. Gather comprehensive information on machine learning applications in finance, including current trends, use cases, and future prospects.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Writer", "description": "Creates technical content and explanations", "system_prompt": "You are a technical writer specializing in machine learning and finance. Create clear, engaging technical content that explains complex concepts in accessible terms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Finance Expert", "description": "Provides financial domain expertise", "system_prompt": "You are a finance expert with knowledge of machine learning applications. Ensure accuracy in financial concepts, market analysis, and industry insights.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Editor", "description": "Reviews and polishes content", "system_prompt": "You are a professional editor. Review content for clarity, flow, accuracy, and overall quality. Make improvements while maintaining technical accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("AgentRearrange swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-A17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Adaptive Content Creation", "description": "Dynamic content creation with flexible agent role assignment", "swarm_type": "AgentRearrange", "output": [ { "role": "Research Specialist", "content": "My research on machine learning in finance reveals key applications in algorithmic trading, risk assessment, fraud detection, and customer service automation..." }, { "role": "Technical Writer", "content": "Building on the research, I've created a comprehensive technical blog post that explains machine learning concepts in finance..." }, { "role": "Finance Expert", "content": "I've reviewed the technical content to ensure financial accuracy, including proper terminology and market insights..." }, { "role": "Editor", "content": "I've edited the content for clarity and flow while maintaining technical accuracy and financial precision..." } ], "number_of_agents": 4, "execution_time": 38.2, "usage": { "input_tokens": 45, "output_tokens": 2800, "total_tokens": 2845, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.000146, "output_token_cost": 0.0259, "token_counts": { "total_input_tokens": 45, "total_output_tokens": 2800, "total_tokens": 2845 }, "num_agents": 4, "night_time_discount_applied": true }, "total_cost": 0.066046, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Design agents with flexible, transferable skills * Use for projects with evolving requirements * Ensure agents can adapt to different roles effectively * Ideal for dynamic workflows and adaptive systems # Auto Agent Builder Source: https://docs.swarms.ai/docs/documentation/multi-agent/auto_agent_builder The Auto Agent Builder API generates a ready-to-run roster of agent configurations from a plain-language task description. A single builder agent analyzes your task and designs the team — names, descriptions, system prompts, and model choices — returning JSON configs you can post directly to the multi-agent endpoints. It never executes the generated agents. ## Overview The Auto Agent Builder generates agent configurations from a task. You describe what you want accomplished; a single builder agent designs the smallest team that covers it and returns each agent's name, description, system prompt, and model choice as ready-to-use `AgentSpec` entries. Two things to know up front: * **It designs, it does not run.** The response contains agent *configurations only* — no agents are constructed or executed, and nothing beyond the single builder call is billed. Pipe the returned roster into [`/v1/swarm/completions`](/docs/documentation/multi-agent/overview) (or any multi-agent endpoint) to actually run it. * **Available on all tiers.** Unlike its siblings Graph Workflow and Batched Grid Workflow, this endpoint is not premium-gated. It is billable, so your account needs a minimum credit balance of \$1.00. **Endpoint:** `POST /v1/auto-agent-builder/completions` **Base URL:** `https://api.swarms.world` (production) or your custom deployment URL ## Architecture ```mermaid theme={null} flowchart LR T["Task description"] --> B["Builder agent"] B --> S["AgentSpec roster"] S -.->|"you run it"| W["/v1/swarm/completions"] ``` The builder only designs the roster. Running it is a separate call you make yourself, shown dashed above. ## Authentication All requests require an API key passed in the `x-api-key` header: ```python theme={null} headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } ``` ## Input Parameters ### AutoAgentBuilderInput Schema | Parameter | Type | Required | Default | Description | | --------------- | --------- | -------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `task` | `string` | Yes | - | The task the generated team should be able to handle. Must be non-empty. | | `name` | `string` | No | `"auto-agent-builder"` | Name for this builder run. | | `description` | `string` | No | `"Generates agent configurations from a task"` | Description of the run. | | `model_name` | `string` | No | builder default | Model backing the **builder agent itself** — not the generated agents; the builder chooses each generated agent's model. Ollama models are rejected with a 400. | | `max_agents` | `integer` | No | `5` | Ceiling on roster size (1-100). The builder prefers the smallest roster that covers the task. | | `num_agents` | `integer` | No | `null` | Exact roster size (1-100). When set, overrides `max_agents` and the prefer-fewer guidance. | | `system_prompt` | `string` | No | builder default | Custom instructions for the builder agent (not the generated agents). | | `agent_kwargs` | `dict` | No | `null` | Extra fields applied to every generated agent (e.g. `max_loops`, `streaming_on`). Keys the builder itself produces (`agent_name`, `description`, `system_prompt`, `model_name`) cannot be overridden and are ignored. | ## Output Parameters ### AutoAgentBuilderOutput Schema | Parameter | Type | Description | | ------------- | ----------------- | ----------------------------------------------------------------------- | | `job_id` | `string` | Unique job identifier, prefixed `auto-agent-builder-`. | | `name` | `string` | Run name from the input (or the default). | | `description` | `string` | Run description from the input (or the default). | | `status` | `string` | `"success"` on completion. | | `agents` | `List[AgentSpec]` | The generated roster. See the note below on which fields are populated. | | `usage` | `Usage` | Token counts and cost for the builder call. | | `timestamp` | `string` | ISO 8601 UTC timestamp. | ### Generated agent entries Each entry in `agents` is an `AgentSpec`, but the builder populates only these fields — do not expect the full AgentSpec surface (e.g. `max_tokens`, `tools_list_dictionary`) unless you supplied it via `agent_kwargs`: | Field | Type | Description | | --------------- | -------- | --------------------------------------------------- | | `agent_name` | `string` | Name the builder chose for the agent. | | `description` | `string` | What the agent is responsible for. | | `system_prompt` | `string` | Full system prompt the builder wrote for the agent. | | `model_name` | `string` | Model the builder selected for the agent. | ### Usage Schema | Field | Type | Description | | ---------------- | --------- | ------------------------------------------------------------------------------ | | `input_tokens` | `integer` | Tokens in your task (plus `system_prompt` if provided). | | `output_tokens` | `integer` | Tokens in the generated roster. | | `total_tokens` | `integer` | Sum of the above. | | `token_cost` | `float` | Total credits charged for this call. | | `cost_per_agent` | `float` | Flat fee for the single builder agent (\$0.01). Not multiplied by roster size. | ## Cost Calculation The endpoint bills one builder-agent call: * Input tokens: \$6.50 per 1M tokens * Output tokens: \$18.50 per 1M tokens * Flat builder-agent fee: \$0.01 `token_cost = input_cost + output_cost + cost_per_agent`. The generated agents cost nothing until you run them. See [Pricing](/docs/documentation/resources/pricing) for current rates. ## Error Responses | Status | Meaning | | ------ | ------------------------------------------------------------------------------------------- | | `400` | Empty or invalid `task`, an Ollama `model_name`, or the builder produced no usable configs. | | `401` | Missing or invalid API key. | | `402` | Account credit balance below the \$1.00 minimum for billable endpoints. | | `422` | Request failed schema validation (e.g. `max_agents` outside 1-100). | | `429` | Rate limit exceeded. | | `500` | Unexpected server error. | ## Examples ### Minimal request ```bash theme={null} curl -X POST "https://api.swarms.world/v1/auto-agent-builder/completions" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "task": "Research the EV battery market and produce an investment memo", "max_agents": 3 }' ``` Example response: ```json theme={null} { "job_id": "auto-agent-builder-8f3a1c2e9b", "name": "auto-agent-builder", "description": "Generates agent configurations from a task", "status": "success", "agents": [ { "agent_name": "MarketResearchAnalyst", "description": "Researches EV battery market trends, key players, and supply chains.", "system_prompt": "You are an expert market research analyst specializing in the EV battery industry...", "model_name": "gpt-4.1" }, { "agent_name": "FinancialAnalyst", "description": "Builds valuation models and financial projections for EV battery companies.", "system_prompt": "You are a financial analyst specializing in investment memos...", "model_name": "gpt-4.1" }, { "agent_name": "InvestmentMemoWriter", "description": "Synthesizes research and analysis into a polished investment memo.", "system_prompt": "You are an investment memo writer...", "model_name": "claude-sonnet-5" } ], "usage": { "input_tokens": 14, "output_tokens": 612, "total_tokens": 626, "token_cost": 0.021413, "cost_per_agent": 0.01 }, "timestamp": "2026-08-13T12:00:00.000000+00:00" } ``` ### Exact roster size with shared agent settings ```python theme={null} import os import requests BASE_URL = "https://api.swarms.world" headers = {"x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json"} response = requests.post( f"{BASE_URL}/v1/auto-agent-builder/completions", headers=headers, json={ "task": "Design, write, and edit a technical blog post about vector databases", "num_agents": 3, "agent_kwargs": {"max_loops": 1, "max_tokens": 4000}, }, timeout=120, ) roster = response.json()["agents"] ``` ### Build a team, then run it The returned roster round-trips unmodified into the swarm endpoint: ```python theme={null} import os import requests BASE_URL = "https://api.swarms.world" headers = {"x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json"} task = "Audit this Python package for security issues and write a findings report" # 1. Design the team built = requests.post( f"{BASE_URL}/v1/auto-agent-builder/completions", headers=headers, json={"task": task, "max_agents": 4}, timeout=120, ).json() # 2. Run it result = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={ "name": "auto-built-audit-team", "swarm_type": "SequentialWorkflow", "task": task, "agents": built["agents"], }, timeout=600, ).json() print(result["output"]) ``` ## Best Practices * **Let the builder decide the size.** `max_agents` is a ceiling, not a target — the builder prefers the smallest team that covers the task. Reach for `num_agents` only when you need an exact count. * **Use `agent_kwargs` for runtime settings.** Fields like `max_loops`, `max_tokens`, or `streaming_on` applied via `agent_kwargs` land on every generated agent; the builder's own choices (`agent_name`, `description`, `system_prompt`, `model_name`) always win over colliding keys. * **Review before running.** The roster is plain JSON — inspect or edit the system prompts and model choices before posting them to a completions endpoint, especially for cost-sensitive workloads. ## Rate Limits Standard tier-based rate limits apply. See [Rate Limits](/docs/documentation/resources/ratelimits). ## Support * Documentation: [https://docs.swarms.ai](https://docs.swarms.ai) * Email: [kye@swarms.world](mailto:kye@swarms.world) * Community: [https://discord.gg/EamjgSaEQf](https://discord.gg/EamjgSaEQf) # Available Multi-Agent Architectures Source: https://docs.swarms.ai/docs/documentation/multi-agent/available-architectures Comprehensive reference of all available multi-agent swarm architectures in the Swarms API ## Overview The Swarms API provides a diverse range of multi-agent architectures, each designed to solve specific types of problems and workflows. These architectures enable you to orchestrate multiple AI agents in various patterns, from simple sequential workflows to complex hierarchical systems. Understanding the available architectures helps you select the optimal pattern for your use case, whether you need parallel processing, consensus-based decision making, or dynamic task routing. Multi-agent architectures can be combined and nested to create sophisticated systems that leverage the strengths of different patterns. Each architecture type has unique characteristics that make it suitable for specific scenarios, such as linear processing pipelines, collaborative problem-solving, or high-throughput batch operations. The flexibility of these architectures allows you to build custom solutions that match your exact requirements. ## Available Architectures The following table provides a comprehensive list of all available multi-agent architectures in the Swarms API: | Swarm Type | Description | Documentation | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | `AgentRearrange` | Dynamically reorganize agents to optimize task performance | [Learn More](/docs/documentation/multi-agent/agent_rearrange) | | `MixtureOfAgents` | Combine diverse specialist agents for complex tasks | [Learn More](/docs/documentation/multi-agent/mixture_of_agents) | | `SequentialWorkflow` | Executes tasks in a strict, predefined order | [Learn More](/docs/documentation/multi-agent/sequential_workflow) | | `ConcurrentWorkflow` | Runs independent tasks in parallel for higher throughput | [Learn More](/docs/documentation/multi-agent/concurrent_workflow) | | `MultiAgentRouter` | Intelligent dispatcher that routes tasks based on capabilities/load | [Learn More](/docs/documentation/multi-agent/multi_agent_router) | | `HierarchicalSwarm` | Multi-level structures with delegation and escalation | [Learn More](/docs/documentation/multi-agent/hierarchical_swarm) | | `MajorityVoting` | Consensus-based decision-making across multiple agents | [Learn More](/docs/documentation/multi-agent/majority_voting) | | `BatchedGridWorkflow` | Execute multiple tasks across multiple agents in a grid pattern | [Learn More](/docs/documentation/multi-agent/batched_grid_workflow) | | `GraphWorkflow` | Execute a graph workflow with directed agent nodes and edges (available via a dedicated `/v1/graph-workflow/completions` endpoint rather than the `swarm_type` field) | [Learn More](/docs/documentation/multi-agent/graph_workflow) | | `GroupChat` | Collaborative problem-solving through conversation | - | | `CouncilAsAJudge` | Council-based evaluation system | - | | `PlannerWorkerSwarm` | Separates planning from execution: planner agents break the task into sub-tasks that worker agents pull from a shared queue | - | | `HeavySwarm` | High-capacity swarm processing | [Learn More](/docs/documentation/multi-agent/heavy_swarm) | | `LLMCouncil` | Language model council for decisions | - | | `DebateWithJudge` | Structured debate with judgment | [Learn More](/docs/documentation/multi-agent/debate_with_judge) | | `RoundRobin` | Round-robin task distribution | [Learn More](/docs/documentation/multi-agent/round_robin) | | `auto` | Automatic swarm type selection | - | ## Architecture Categories The available architectures can be broadly categorized into several groups: **Workflow Patterns**: `SequentialWorkflow`, `ConcurrentWorkflow`, `GraphWorkflow`, and `BatchedGridWorkflow` provide different execution patterns for organizing agent tasks. **Collaboration Patterns**: `GroupChat`, `MixtureOfAgents`, and `MajorityVoting` enable agents to work together collaboratively. **Routing & Organization**: `MultiAgentRouter`, `HierarchicalSwarm`, `AgentRearrange`, `RoundRobin`, and `PlannerWorkerSwarm` help organize and distribute work among agents. **Specialized Systems**: `HeavySwarm` provides specialized capabilities for specific use cases. **Decision & Evaluation**: `MajorityVoting`, `CouncilAsAJudge`, `DebateWithJudge`, and `LLMCouncil` focus on decision-making and evaluation processes. ## Getting Started To use any of these architectures, make a request to the `/v1/swarm/completions` endpoint with the `swarm_type` parameter set to your desired architecture. For detailed information about each architecture, including usage examples and best practices, follow the links in the table above or refer to the [Multi-Agent Overview](/docs/documentation/multi-agent/overview) page. # BatchedGridWorkflow Source: https://docs.swarms.ai/docs/documentation/multi-agent/batched_grid_workflow Execute multiple tasks across multiple agents in a grid pattern, with each agent processing all tasks in parallel batches **Swarm Type**: `BatchedGridWorkflow` **Premium Tier Required**: The `/v1/batched-grid-workflow/completions` endpoint is restricted to Pro, Ultra, and Premium plan subscribers. Free tier users will receive a 403 error. [Upgrade your account](https://swarms.world/platform/account) to access batched grid workflow capabilities. ## Overview The BatchedGridWorkflow swarm type executes multiple tasks across multiple agents in a grid-like pattern, where each agent processes every task independently. This creates a comprehensive matrix of results, allowing you to compare how different agents approach the same set of tasks. The workflow supports iterative refinement through the `max_loops` parameter, enabling agents to improve their outputs over multiple iterations. Key features: * **Grid Execution Pattern**: Each agent processes every task, creating a complete task-agent matrix * **Parallel Batch Processing**: All agent-task combinations run in parallel for maximum efficiency * **Iterative Refinement**: Support for multiple loops to refine and improve outputs * **Comparative Analysis**: Easy comparison of different agent approaches to the same tasks * **Structured Output Mapping**: Results organized by agent name for each task ## Architecture ```mermaid theme={null} flowchart LR T1["Task 1"] --> A1["Agent 1"] T1 --> A2["Agent 2"] T2["Task 2"] --> A1 T2 --> A2 A1 --> G["Results grid"] A2 --> G ``` Every agent runs every task, so the output is a matrix: one result per agent-task pair. ## Use Cases * A/B testing different agent configurations on the same tasks * Multi-perspective analysis where each expert reviews all aspects * Quality assurance with multiple reviewers checking all items * Comparative research across different methodological approaches * Content generation with multiple styles or tones for the same topics ## API Usage ### Basic BatchedGridWorkflow Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/batched-grid-workflow/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Product Review Analysis Grid", "description": "Multiple analysts reviewing multiple product categories", "agent_completions": [ { "agent_name": "Technical Analyst", "description": "Focuses on technical specifications and performance", "system_prompt": "You are a technical analyst. Evaluate products based on specifications, performance metrics, build quality, and technical innovation.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "User Experience Analyst", "description": "Focuses on usability and user satisfaction", "system_prompt": "You are a UX analyst. Evaluate products based on ease of use, user interface, customer satisfaction, and overall user experience.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Value Analyst", "description": "Focuses on pricing and value proposition", "system_prompt": "You are a value analyst. Evaluate products based on pricing, cost-effectiveness, ROI, and overall value for money.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "tasks": [ "Analyze the smartphone market segment and top products", "Analyze the laptop market segment and top products", "Analyze the tablet market segment and top products" ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } workflow_config = { "name": "Product Review Analysis Grid", "description": "Multiple analysts reviewing multiple product categories", "agent_completions": [ { "agent_name": "Technical Analyst", "description": "Focuses on technical specifications and performance", "system_prompt": "You are a technical analyst. Evaluate products based on specifications, performance metrics, build quality, and technical innovation.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "User Experience Analyst", "description": "Focuses on usability and user satisfaction", "system_prompt": "You are a UX analyst. Evaluate products based on ease of use, user interface, customer satisfaction, and overall user experience.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Value Analyst", "description": "Focuses on pricing and value proposition", "system_prompt": "You are a value analyst. Evaluate products based on pricing, cost-effectiveness, ROI, and overall value for money.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "tasks": [ "Analyze the smartphone market segment and top products", "Analyze the laptop market segment and top products", "Analyze the tablet market segment and top products" ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/batched-grid-workflow/completions", headers=headers, json=workflow_config ) if response.status_code == 200: result = response.json() print("BatchedGridWorkflow completed successfully!") print(f"Job ID: {result['job_id']}") print(f"Total cost: ${result['usage']['token_cost']}") print(f"Output tokens: {result['usage']['output_tokens']}") # Access results by task and agent for task_idx, task_results in enumerate(result['outputs']): print(f"\nTask {task_idx + 1} results:") for agent_name, output in task_results.items(): print(f" {agent_name}: {output[:100]}...") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const workflowConfig = { name: "Product Review Analysis Grid", description: "Multiple analysts reviewing multiple product categories", agent_completions: [ { agent_name: "Technical Analyst", description: "Focuses on technical specifications and performance", system_prompt: "You are a technical analyst. Evaluate products based on specifications, performance metrics, build quality, and technical innovation.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "User Experience Analyst", description: "Focuses on usability and user satisfaction", system_prompt: "You are a UX analyst. Evaluate products based on ease of use, user interface, customer satisfaction, and overall user experience.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 }, { agent_name: "Value Analyst", description: "Focuses on pricing and value proposition", system_prompt: "You are a value analyst. Evaluate products based on pricing, cost-effectiveness, ROI, and overall value for money.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], tasks: [ "Analyze the smartphone market segment and top products", "Analyze the laptop market segment and top products", "Analyze the tablet market segment and top products" ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/batched-grid-workflow/completions`, { method: "POST", headers: headers, body: JSON.stringify(workflowConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("BatchedGridWorkflow completed successfully!"); console.log(`Job ID: ${result.job_id}`); console.log(`Total cost: $${result.usage.token_cost}`); console.log(`Output tokens: ${result.usage.output_tokens}`); // Access results by task and agent result.outputs.forEach((taskResults, taskIdx) => { console.log(`\nTask ${taskIdx + 1} results:`); for (const [agentName, output] of Object.entries(taskResults)) { console.log(` ${agentName}: ${output.substring(0, 100)}...`); } }); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type AgentSpec struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type WorkflowConfig struct { Name string `json:"name"` Description string `json:"description"` AgentCompletions []AgentSpec `json:"agent_completions"` Tasks []string `json:"tasks"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" workflowConfig := WorkflowConfig{ Name: "Product Review Analysis Grid", Description: "Multiple analysts reviewing multiple product categories", AgentCompletions: []AgentSpec{ { AgentName: "Technical Analyst", Description: "Focuses on technical specifications and performance", SystemPrompt: "You are a technical analyst. Evaluate products based on specifications, performance metrics, build quality, and technical innovation.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "User Experience Analyst", Description: "Focuses on usability and user satisfaction", SystemPrompt: "You are a UX analyst. Evaluate products based on ease of use, user interface, customer satisfaction, and overall user experience.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, { AgentName: "Value Analyst", Description: "Focuses on pricing and value proposition", SystemPrompt: "You are a value analyst. Evaluate products based on pricing, cost-effectiveness, ROI, and overall value for money.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, Tasks: []string{ "Analyze the smartphone market segment and top products", "Analyze the laptop market segment and top products", "Analyze the tablet market segment and top products", }, MaxLoops: 1, } jsonData, _ := json.Marshal(workflowConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/batched-grid-workflow/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let workflow_config = json!({ "name": "Product Review Analysis Grid", "description": "Multiple analysts reviewing multiple product categories", "agent_completions": [ { "agent_name": "Technical Analyst", "description": "Focuses on technical specifications and performance", "system_prompt": "You are a technical analyst. Evaluate products based on specifications, performance metrics, build quality, and technical innovation.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "User Experience Analyst", "description": "Focuses on usability and user satisfaction", "system_prompt": "You are a UX analyst. Evaluate products based on ease of use, user interface, customer satisfaction, and overall user experience.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Value Analyst", "description": "Focuses on pricing and value proposition", "system_prompt": "You are a value analyst. Evaluate products based on pricing, cost-effectiveness, ROI, and overall value for money.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "tasks": [ "Analyze the smartphone market segment and top products", "Analyze the laptop market segment and top products", "Analyze the tablet market segment and top products" ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/batched-grid-workflow/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&workflow_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("BatchedGridWorkflow completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "batched-grid-workflow-XyZ123AbC456", "name": "Product Review Analysis Grid", "description": "Multiple analysts reviewing multiple product categories", "status": "success", "outputs": [ { "Technical Analyst": "Smartphone Market Analysis: The current smartphone market is dominated by flagship devices with advanced processors (Snapdragon 8 Gen 3, Apple A17 Pro), high refresh rate displays (120Hz+), and improved camera systems with computational photography...", "User Experience Analyst": "Smartphone Market Analysis: Modern smartphones excel in user experience with intuitive interfaces, gesture navigation, and seamless ecosystem integration. Top products like iPhone 15 Pro and Samsung Galaxy S24 Ultra offer polished UX with minimal learning curves...", "Value Analyst": "Smartphone Market Analysis: The smartphone market offers varied value propositions. Flagship devices ($800-$1200) provide premium features but face strong competition from mid-range options ($400-$600) that deliver 80% of the performance at half the cost..." }, { "Technical Analyst": "Laptop Market Analysis: The laptop segment showcases impressive technical advancement with Apple's M3 chips, Intel's 14th Gen processors, and AMD's Ryzen 7000 series. Performance metrics show 40% improvements in multi-core workloads...", "User Experience Analyst": "Laptop Market Analysis: User experience varies significantly by form factor and OS. MacBook Air/Pro lead in build quality and battery life, while Windows ultrabooks like Dell XPS offer flexibility. Gaming laptops trade portability for performance...", "Value Analyst": "Laptop Market Analysis: Value positioning spans from budget Chromebooks ($300-$500) to premium workstations ($2000+). Best value currently found in mid-tier business laptops ($800-$1200) offering professional features without premium pricing..." }, { "Technical Analyst": "Tablet Market Analysis: Tablet technology centers on display quality (OLED, mini-LED), processor efficiency (M2, Snapdragon 8 Gen 2), and stylus integration. iPad Pro and Galaxy Tab S9 Ultra lead with desktop-class performance...", "User Experience Analyst": "Tablet Market Analysis: Tablets excel for content consumption and creative work. iPad ecosystem offers superior app quality, while Android tablets provide better customization. Surface Pro bridges tablet-laptop gap with full desktop OS...", "Value Analyst": "Tablet Market Analysis: Tablet value depends on use case. Budget tablets ($200-$400) suit basic needs, while premium options ($800-$1300) justify cost for professionals and creatives. Mid-tier options ($400-$600) offer best balance..." } ], "usage": { "input_tokens": 450, "output_tokens": 4850, "total_tokens": 5300, "token_cost": 0.12265, "cost_per_agent": 0.03 }, "timestamp": "2025-01-12T10:30:45.123456Z" } ``` ## Advanced Example: Multi-Loop Refinement ```python theme={null} import requests API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } # Example with multiple loops for iterative refinement workflow_config = { "name": "Creative Writing Grid with Refinement", "description": "Multiple writing styles with iterative improvement", "agent_completions": [ { "agent_name": "Technical Writer", "description": "Clear, precise technical writing", "system_prompt": "You are a technical writer. Write clearly and precisely, focusing on accuracy and comprehensibility. In subsequent loops, refine based on previous output.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Creative Writer", "description": "Engaging, narrative-driven writing", "system_prompt": "You are a creative writer. Write engagingly with vivid descriptions and narrative flow. In subsequent loops, enhance the storytelling elements.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.7 }, { "agent_name": "Academic Writer", "description": "Formal, research-oriented writing", "system_prompt": "You are an academic writer. Write formally with citations, evidence-based arguments, and scholarly tone. In subsequent loops, strengthen the academic rigor.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "tasks": [ "Write about the impact of artificial intelligence on society", "Write about climate change solutions" ], "max_loops": 3 # Run 3 iterations for refinement } response = requests.post( f"{API_BASE_URL}/v1/batched-grid-workflow/completions", headers=headers, json=workflow_config ) if response.status_code == 200: result = response.json() print(f"Workflow completed with {workflow_config['max_loops']} refinement loops") print(f"Total tokens: {result['usage']['total_tokens']}") print(f"Total cost: ${result['usage']['token_cost']:.4f}") # Compare different writing styles for each topic for task_idx, task_results in enumerate(result['outputs']): print(f"\n{'='*60}") print(f"Topic {task_idx + 1}") print('='*60) for agent_name, output in task_results.items(): print(f"\n{agent_name}:") print(output[:200] + "...") else: print(f"Error: {response.status_code} - {response.text}") ``` ## Request Schema ### BatchedGridWorkflowInput | Field | Type | Required | Description | | ------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | string | No | The name of the batched grid workflow | | `description` | string | No | A description of what the workflow does | | `agent_completions` | array | Yes | List of agent configurations (see AgentSpec below) | | `tasks` | array | Yes | List of tasks that each agent will process | | `max_loops` | integer | No | Number of iterations for refinement (default: 1). Must be between 1 and 50 — values outside that range are rejected with a `422` validation error | | `imgs` | array | No | Accepted for forward compatibility, but not currently used in execution — passing images here has no effect on the run | ### AgentSpec | Field | Type | Required | Description | | --------------- | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------- | | `agent_name` | string | Yes | Unique name for the agent | | `description` | string | No | Description of the agent's role | | `system_prompt` | string | No | System prompt defining agent behavior | | `model_name` | string | No | Model to use (e.g., "gpt-4.1", "claude-sonnet-4-20250514"); defaults to `claude-sonnet-5` | | `max_loops` | integer or string | No | Max loops per agent, or `"auto"` (default: 1) | | `max_tokens` | integer | No | Maximum tokens the agent can generate (default: 16000); values below 1 are rejected with a 422 validation error | | `temperature` | float | No | Sampling temperature; if omitted, the provider's own default applies | | `role` | string | No | Agent's role within the swarm (default: "worker") | ## Response Schema ### BatchedGridWorkflowOutput | Field | Type | Description | | ------------- | ------ | ------------------------------------------------------------------------- | | `job_id` | string | Unique identifier for the workflow execution | | `name` | string | Name of the workflow | | `description` | string | Description of the workflow | | `status` | string | Execution status ("success" or "error") | | `outputs` | array | Array of task results, each containing agent outputs mapped by agent name | | `usage` | object | Token usage and cost information | | `timestamp` | string | ISO 8601 timestamp of completion | ### Usage Object | Field | Type | Description | | ---------------- | ------- | ------------------------------------------------------------------------------------- | | `input_tokens` | integer | Total input tokens consumed | | `output_tokens` | integer | Total output tokens generated | | `total_tokens` | integer | Sum of input and output tokens | | `token_cost` | float | Total credits charged for the run: input and output token costs plus `cost_per_agent` | | `cost_per_agent` | float | Fixed cost per agent (0.01 credits per agent) | ## Pricing BatchedGridWorkflow uses unified pricing with agent costs. For detailed pricing information, see the Pricing page. ## Grid Execution Pattern The BatchedGridWorkflow creates a matrix where: * **Rows**: Represent tasks * **Columns**: Represent agents * **Cells**: Contain each agent's response to each task ``` Agent 1 Agent 2 Agent 3 Task 1 [Response 1.1] [Response 1.2] [Response 1.3] Task 2 [Response 2.1] [Response 2.2] [Response 2.3] Task 3 [Response 3.1] [Response 3.2] [Response 3.3] ``` The output structure groups results by task: ```python theme={null} outputs = [ { # Task 1 results "Agent 1": "Response 1.1", "Agent 2": "Response 1.2", "Agent 3": "Response 1.3" }, { # Task 2 results "Agent 1": "Response 2.1", "Agent 2": "Response 2.2", "Agent 3": "Response 2.3" } ] ``` ## Best Practices ### When to Use BatchedGridWorkflow * **Comparative Analysis**: Need multiple perspectives on the same set of tasks * **A/B Testing**: Testing different agent configurations on identical inputs * **Multi-Expert Review**: Multiple specialists reviewing the same items * **Style Variations**: Generating content in different styles or tones * **Quality Assurance**: Multiple reviewers checking all aspects ### When to Use Other Workflows * **Sequential dependencies**: Use [SequentialWorkflow](/docs/documentation/multi-agent/sequential_workflow) * **Independent parallel tasks**: Use [ConcurrentWorkflow](/docs/documentation/multi-agent/concurrent_workflow) * **Task routing**: Use [MultiAgentRouter](/docs/documentation/multi-agent/multi_agent_router) * **Consensus decisions**: Use [MajorityVoting](/docs/documentation/multi-agent/majority_voting) ### Design Recommendations 1. **Agent Diversity**: Design agents with distinct specializations for meaningful comparisons 2. **Task Granularity**: Break complex topics into specific tasks for better analysis 3. **Temperature Settings**: Use lower temperatures (0.3-0.5) for analytical tasks, higher (0.6-0.8) for creative tasks 4. **Iterative Refinement**: Use `max_loops > 1` when quality improvement is worth the added cost 5. **Result Processing**: Implement post-processing to compare and synthesize agent outputs ### Cost Optimization * Start with fewer agents and tasks to test your workflow * Use appropriate models (`claude-sonnet-4-20250514` or `gpt-4.1` for quality, `gpt-4.1-mini` for cost) * Monitor token usage and adjust prompt verbosity * Cache common results when possible * Batch multiple related workflows in a single session ## Error Handling The API returns standard HTTP status codes: * **200**: Success * **400**: Bad request (invalid configuration) * **401**: Unauthorized (invalid API key) * **402**: Payment required (insufficient credits) * **500**: Server error Example error response: ```json theme={null} { "detail": "BatchedGridWorkflowCompletionError: Invalid agent configuration" } ``` ## Limitations * Maximum recommended: 10 agents × 10 tasks (100 total executions per workflow) * Each agent-task combination counts toward rate limits * Large grids may experience longer processing times * Token limits apply per agent execution ## Related Workflows * [SequentialWorkflow](/docs/documentation/multi-agent/sequential_workflow) - For step-by-step processing * [ConcurrentWorkflow](/docs/documentation/multi-agent/concurrent_workflow) - For parallel independent tasks * [MixtureOfAgents](/docs/documentation/multi-agent/mixture_of_agents) - For combining diverse specialists * [MajorityVoting](/docs/documentation/multi-agent/majority_voting) - For consensus-based decisions # ConcurrentWorkflow Source: https://docs.swarms.ai/docs/documentation/multi-agent/concurrent_workflow Parallel execution swarm that runs independent tasks simultaneously for faster processing and improved efficiency **Swarm Type**: `ConcurrentWorkflow` ## Overview The ConcurrentWorkflow swarm type runs independent tasks in parallel, significantly reducing processing time for complex operations. This architecture is ideal for tasks that can be processed simultaneously without dependencies, allowing multiple agents to work on different aspects of a problem at the same time. Key features: * **Parallel Execution**: Multiple agents work simultaneously * **Reduced Processing Time**: Faster completion through parallelization * **Independent Tasks**: Agents work on separate, non-dependent subtasks * **Scalable Performance**: Performance scales with the number of agents ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A1["Agent 1"] T --> A2["Agent 2"] T --> A3["Agent 3"] A1 --> R["Results"] A2 --> R A3 --> R ``` All agents start at once and work independently. No agent waits on another. ## Use Cases * Independent data analysis tasks * Parallel content generation * Multi-source research projects * Distributed problem solving ## API Usage ### Basic ConcurrentWorkflow Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Market Research Concurrent", "description": "Parallel market research across different sectors", "swarm_type": "ConcurrentWorkflow", "task": "Research and analyze market opportunities in AI, healthcare, fintech, and e-commerce sectors", "agents": [ { "agent_name": "AI Market Analyst", "description": "Analyzes AI market trends and opportunities", "system_prompt": "You are an AI market analyst. Focus on artificial intelligence market trends, opportunities, key players, and growth projections.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Healthcare Market Analyst", "description": "Analyzes healthcare market trends", "system_prompt": "You are a healthcare market analyst. Focus on healthcare market trends, digital health opportunities, regulatory landscape, and growth areas.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Fintech Market Analyst", "description": "Analyzes fintech market opportunities", "system_prompt": "You are a fintech market analyst. Focus on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "E-commerce Market Analyst", "description": "Analyzes e-commerce market trends", "system_prompt": "You are an e-commerce market analyst. Focus on online retail trends, marketplace opportunities, consumer behavior, and emerging platforms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Market Research Concurrent", "description": "Parallel market research across different sectors", "swarm_type": "ConcurrentWorkflow", "task": "Research and analyze market opportunities in AI, healthcare, fintech, and e-commerce sectors", "agents": [ { "agent_name": "AI Market Analyst", "description": "Analyzes AI market trends and opportunities", "system_prompt": "You are an AI market analyst. Focus on artificial intelligence market trends, opportunities, key players, and growth projections.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Healthcare Market Analyst", "description": "Analyzes healthcare market trends", "system_prompt": "You are a healthcare market analyst. Focus on healthcare market trends, digital health opportunities, regulatory landscape, and growth areas.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Fintech Market Analyst", "description": "Analyzes fintech market opportunities", "system_prompt": "You are a fintech market analyst. Focus on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "E-commerce Market Analyst", "description": "Analyzes e-commerce market trends", "system_prompt": "You are an e-commerce market analyst. Focus on online retail trends, marketplace opportunities, consumer behavior, and emerging platforms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("ConcurrentWorkflow swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Parallel results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Market Research Concurrent", description: "Parallel market research across different sectors", swarm_type: "ConcurrentWorkflow", task: "Research and analyze market opportunities in AI, healthcare, fintech, and e-commerce sectors", agents: [ { agent_name: "AI Market Analyst", description: "Analyzes AI market trends and opportunities", system_prompt: "You are an AI market analyst. Focus on artificial intelligence market trends, opportunities, key players, and growth projections.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Healthcare Market Analyst", description: "Analyzes healthcare market trends", system_prompt: "You are a healthcare market analyst. Focus on healthcare market trends, digital health opportunities, regulatory landscape, and growth areas.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Fintech Market Analyst", description: "Analyzes fintech market opportunities", system_prompt: "You are a fintech market analyst. Focus on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "E-commerce Market Analyst", description: "Analyzes e-commerce market trends", system_prompt: "You are an e-commerce market analyst. Focus on online retail trends, marketplace opportunities, consumer behavior, and emerging platforms.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("ConcurrentWorkflow swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Parallel results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Market Research Concurrent", Description: "Parallel market research across different sectors", SwarmType: "ConcurrentWorkflow", Task: "Research and analyze market opportunities in AI, healthcare, fintech, and e-commerce sectors", Agents: []Agent{ { AgentName: "AI Market Analyst", Description: "Analyzes AI market trends and opportunities", SystemPrompt: "You are an AI market analyst. Focus on artificial intelligence market trends, opportunities, key players, and growth projections.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Healthcare Market Analyst", Description: "Analyzes healthcare market trends", SystemPrompt: "You are a healthcare market analyst. Focus on healthcare market trends, digital health opportunities, regulatory landscape, and growth areas.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Fintech Market Analyst", Description: "Analyzes fintech market opportunities", SystemPrompt: "You are a fintech market analyst. Focus on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "E-commerce Market Analyst", Description: "Analyzes e-commerce market trends", SystemPrompt: "You are an e-commerce market analyst. Focus on online retail trends, marketplace opportunities, consumer behavior, and emerging platforms.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Market Research Concurrent", "description": "Parallel market research across different sectors", "swarm_type": "ConcurrentWorkflow", "task": "Research and analyze market opportunities in AI, healthcare, fintech, and e-commerce sectors", "agents": [ { "agent_name": "AI Market Analyst", "description": "Analyzes AI market trends and opportunities", "system_prompt": "You are an AI market analyst. Focus on artificial intelligence market trends, opportunities, key players, and growth projections.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Healthcare Market Analyst", "description": "Analyzes healthcare market trends", "system_prompt": "You are a healthcare market analyst. Focus on healthcare market trends, digital health opportunities, regulatory landscape, and growth areas.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Fintech Market Analyst", "description": "Analyzes fintech market opportunities", "system_prompt": "You are a fintech market analyst. Focus on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "E-commerce Market Analyst", "description": "Analyzes e-commerce market trends", "system_prompt": "You are an e-commerce market analyst. Focus on online retail trends, marketplace opportunities, consumer behavior, and emerging platforms.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("ConcurrentWorkflow swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-S17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Market Research Concurrent", "description": "Parallel market research across different sectors", "swarm_type": "ConcurrentWorkflow", "output": [ { "role": "E-commerce Market Analyst", "content": "To analyze market opportunities in the AI, healthcare, fintech, and e-commerce sectors, we can break down each sector's current trends, consumer behavior, and emerging platforms. Here's an overview of each sector with a focus on e-commerce....." }, { "role": "AI Market Analyst", "content": "The artificial intelligence (AI) landscape presents numerous opportunities across various sectors, particularly in healthcare, fintech, and e-commerce. Here's a detailed analysis of each sector:\n\n### Healthcare....." }, { "role": "Healthcare Market Analyst", "content": "As a Healthcare Market Analyst, I will focus on analyzing market opportunities within the healthcare sector, particularly in the realm of AI and digital health. The intersection of healthcare with fintech and e-commerce also presents unique opportunities. Here's an overview of key trends and growth areas:...." }, { "role": "Fintech Market Analyst", "content": "Certainly! Let's break down the market opportunities in the fintech sector, focusing on financial technology trends, digital payment systems, blockchain opportunities, and regulatory developments:\n\n### 1. Financial Technology Trends....." } ], "number_of_agents": 4, "execution_time": 23.360230922698975, "usage": { "input_tokens": 35, "output_tokens": 2787, "total_tokens": 2822, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.000114, "output_token_cost": 0.02578, "token_counts": { "total_input_tokens": 35, "total_output_tokens": 2787, "total_tokens": 2822 }, "num_agents": 4, "night_time_discount_applied": true }, "total_cost": 0.065894, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Design independent tasks that don't require sequential dependencies * Use for tasks that can be parallelized effectively * Ensure agents have distinct, non-overlapping responsibilities * Ideal for time-sensitive analysis requiring multiple perspectives # DebateWithJudge Source: https://docs.swarms.ai/docs/documentation/multi-agent/debate_with_judge Structured debate architecture where a Pro agent and Con agent present opposing arguments, evaluated and synthesized by an impartial Judge agent through progressive refinement loops **Swarm Type**: `DebateWithJudge` ## Overview The DebateWithJudge swarm type implements a structured debate architecture with progressive self-refinement. Two debater agents — one arguing in favor (Pro) and one arguing against (Con) — present opposing arguments on a given topic. An impartial Judge agent evaluates both sides, provides feedback, and synthesizes the strongest elements into a refined answer. This process repeats over multiple loops, with each round producing progressively better arguments and a more nuanced final synthesis. Key features: * **Structured Argumentation**: Pro and Con agents present opposing perspectives with evidence-based reasoning * **Impartial Evaluation**: A Judge agent objectively assesses argument quality and provides constructive feedback * **Progressive Refinement**: Each debate loop builds on the judge's synthesis, producing increasingly refined arguments * **Convergent Synthesis**: The final output combines the strongest elements from both sides into a well-reasoned conclusion ## Architecture ```mermaid theme={null} flowchart TD T["Topic"] --> P["Pro agent"] T --> C["Con agent"] P --> J["Judge"] C --> J J --> S["Refined synthesis"] S -.->|"next loop"| P S -.->|"next loop"| C ``` Pro and Con argue, the Judge evaluates both and synthesizes. Each loop restarts the debate from that synthesis, so the arguments sharpen with every round. ## Use Cases * Policy analysis requiring balanced pro/con evaluation * Strategic decision-making with structured trade-off analysis * Risk assessment where both opportunities and threats need rigorous examination * Technology evaluation comparing competing approaches * Investment analysis weighing bull and bear cases * Ethical dilemma resolution with multi-perspective reasoning ## API Usage ### Basic DebateWithJudge Example The DebateWithJudge architecture requires exactly **3 agents** in a specific order: 1. **Pro Agent** — argues in favor of the proposition 2. **Con Agent** — argues against the proposition 3. **Judge Agent** — evaluates both sides and provides synthesis ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Work Policy Debate", "description": "Structured debate on workplace policy with judge evaluation", "swarm_type": "DebateWithJudge", "task": "Should companies adopt a mandatory 4-day work week? Consider productivity impact, employee wellbeing, competitive dynamics, and implementation challenges.", "agents": [ { "agent_name": "Pro Advocate", "description": "Argues in favor of the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing IN FAVOR of the proposition. Present compelling, well-structured arguments supported by evidence, data, and concrete examples. Anticipate counterarguments and address them proactively. If this is a refinement round, strengthen your arguments based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Con Advocate", "description": "Argues against the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing AGAINST the proposition. Present compelling counter-arguments, identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world examples. If this is a refinement round, strengthen your opposition based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Impartial Judge", "description": "Evaluates arguments from both sides and provides synthesis", "system_prompt": "You are an impartial judge evaluating a structured debate. Objectively assess the strength of arguments from both sides based on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side and synthesize them into a balanced, well-reasoned conclusion. Provide a clear final verdict with justification.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Work Policy Debate", "description": "Structured debate on workplace policy with judge evaluation", "swarm_type": "DebateWithJudge", "task": "Should companies adopt a mandatory 4-day work week? Consider productivity impact, employee wellbeing, competitive dynamics, and implementation challenges.", "agents": [ { "agent_name": "Pro Advocate", "description": "Argues in favor of the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing IN FAVOR of the proposition. Present compelling, well-structured arguments supported by evidence, data, and concrete examples. Anticipate counterarguments and address them proactively. If this is a refinement round, strengthen your arguments based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Con Advocate", "description": "Argues against the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing AGAINST the proposition. Present compelling counter-arguments, identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world examples. If this is a refinement round, strengthen your opposition based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Impartial Judge", "description": "Evaluates arguments from both sides and provides synthesis", "system_prompt": "You are an impartial judge evaluating a structured debate. Objectively assess the strength of arguments from both sides based on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side and synthesize them into a balanced, well-reasoned conclusion. Provide a clear final verdict with justification.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print(json.dumps(result["output"], indent=2)) else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Work Policy Debate", description: "Structured debate on workplace policy with judge evaluation", swarm_type: "DebateWithJudge", task: "Should companies adopt a mandatory 4-day work week? Consider productivity impact, employee wellbeing, competitive dynamics, and implementation challenges.", agents: [ { agent_name: "Pro Advocate", description: "Argues in favor of the proposition with evidence-based reasoning", system_prompt: "You are an expert debater arguing IN FAVOR of the proposition. Present compelling, well-structured arguments supported by evidence, data, and concrete examples. Anticipate counterarguments and address them proactively. If this is a refinement round, strengthen your arguments based on the judge feedback.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.5 }, { agent_name: "Con Advocate", description: "Argues against the proposition with evidence-based reasoning", system_prompt: "You are an expert debater arguing AGAINST the proposition. Present compelling counter-arguments, identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world examples. If this is a refinement round, strengthen your opposition based on the judge feedback.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.5 }, { agent_name: "Impartial Judge", description: "Evaluates arguments from both sides and provides synthesis", system_prompt: "You are an impartial judge evaluating a structured debate. Objectively assess the strength of arguments from both sides based on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side and synthesize them into a balanced, well-reasoned conclusion. Provide a clear final verdict with justification.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("DebateWithJudge swarm completed successfully!"); result.output.forEach(output => { console.log(`\n${output.role}: ${output.content}`); }); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Work Policy Debate", Description: "Structured debate on workplace policy with judge evaluation", SwarmType: "DebateWithJudge", Task: "Should companies adopt a mandatory 4-day work week? Consider productivity impact, employee wellbeing, competitive dynamics, and implementation challenges.", Agents: []Agent{ { AgentName: "Pro Advocate", Description: "Argues in favor of the proposition with evidence-based reasoning", SystemPrompt: "You are an expert debater arguing IN FAVOR of the proposition. Present compelling, well-structured arguments supported by evidence, data, and concrete examples. Anticipate counterarguments and address them proactively. If this is a refinement round, strengthen your arguments based on the judge feedback.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Con Advocate", Description: "Argues against the proposition with evidence-based reasoning", SystemPrompt: "You are an expert debater arguing AGAINST the proposition. Present compelling counter-arguments, identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world examples. If this is a refinement round, strengthen your opposition based on the judge feedback.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Impartial Judge", Description: "Evaluates arguments from both sides and provides synthesis", SystemPrompt: "You are an impartial judge evaluating a structured debate. Objectively assess the strength of arguments from both sides based on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side and synthesize them into a balanced, well-reasoned conclusion. Provide a clear final verdict with justification.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Work Policy Debate", "description": "Structured debate on workplace policy with judge evaluation", "swarm_type": "DebateWithJudge", "task": "Should companies adopt a mandatory 4-day work week? Consider productivity impact, employee wellbeing, competitive dynamics, and implementation challenges.", "agents": [ { "agent_name": "Pro Advocate", "description": "Argues in favor of the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing IN FAVOR of the proposition. Present compelling, well-structured arguments supported by evidence, data, and concrete examples. Anticipate counterarguments and address them proactively. If this is a refinement round, strengthen your arguments based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Con Advocate", "description": "Argues against the proposition with evidence-based reasoning", "system_prompt": "You are an expert debater arguing AGAINST the proposition. Present compelling counter-arguments, identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world examples. If this is a refinement round, strengthen your opposition based on the judge feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Impartial Judge", "description": "Evaluates arguments from both sides and provides synthesis", "system_prompt": "You are an impartial judge evaluating a structured debate. Objectively assess the strength of arguments from both sides based on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side and synthesize them into a balanced, well-reasoned conclusion. Provide a clear final verdict with justification.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("DebateWithJudge swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-D8kW2mPxLnRcYvT4qH9sJE", "status": "success", "swarm_name": "Work Policy Debate", "description": "Structured debate on workplace policy with judge evaluation", "swarm_type": "DebateWithJudge", "output": [ { "role": "Pro Advocate", "content": "The case for a 4-day work week is compelling and backed by growing evidence. Microsoft Japan's 2019 trial saw a 40% productivity increase. Iceland's 2015-2019 trial across 2,500 workers showed maintained or improved productivity with significantly better employee wellbeing. A 4-day week reduces burnout (Gallup reports 76% of workers experience burnout at least sometimes), lowers turnover costs (replacing an employee costs 50-200% of salary), and gives companies a powerful recruiting advantage in a tight labor market. The compressed schedule forces better meeting discipline and eliminates low-value work. Companies like Bolt, Buffer, and Kickstarter have adopted it permanently with positive results." }, { "role": "Con Advocate", "content": "While the headline stats are attractive, the 4-day work week has significant practical problems. First, the trials cherry-pick: Microsoft Japan's results came from a single month-long experiment with other simultaneous changes. Most successful cases are in knowledge work — manufacturing, healthcare, retail, and customer service cannot simply compress schedules without service gaps. Second, a mandatory policy removes flexibility: some employees prefer 5 shorter days, and some roles require daily client contact. Third, competitive risk: if your competitors operate 5 days and you operate 4, response times suffer. Finally, implementation costs are real — you may need to hire additional staff for coverage, offsetting any productivity gains." }, { "role": "Impartial Judge", "content": "Both sides present valid arguments. The Pro side effectively demonstrates productivity benefits with concrete data from Microsoft Japan and Iceland trials, and correctly identifies recruiting and retention advantages. The Con side raises important practical limitations, particularly around industry applicability and the weakness of short-term trial data. My synthesis: a 4-day work week should not be mandated universally but adopted selectively. Knowledge-work companies with output-based metrics are strong candidates. Companies should run 3-6 month pilots with clear KPIs before committing. The evidence supports that well-implemented compressed schedules can maintain productivity while improving wellbeing, but the approach must be tailored to industry, role type, and company culture rather than applied as a blanket policy." } ], "number_of_agents": 3, "execution_time": 28.7, "usage": { "input_tokens": 38, "output_tokens": 1800, "total_tokens": 1838, "billing_info": { "cost_breakdown": { "agent_cost": 0.03, "input_token_cost": 0.000247, "output_token_cost": 0.0333, "token_counts": { "total_input_tokens": 38, "total_output_tokens": 1800, "total_tokens": 1838 }, "num_agents": 3, "night_time_discount_applied": false }, "total_cost": 0.063547, "discount_active": false } } } ``` ## Best Practices * Always provide exactly 3 agents in the correct order: Pro (first), Con (second), Judge (third) * Design Pro and Con prompts to be balanced in depth — a one-sided debate produces a weak synthesis * Use lower temperature (0.3-0.4) for the Judge agent to ensure consistent, objective evaluation * Increase `max_loops` for complex topics that benefit from multiple rounds of refinement — each loop produces stronger arguments * DebateWithJudge works best for binary or comparative questions where opposing perspectives add genuine analytical value # GraphWorkflow Source: https://docs.swarms.ai/docs/documentation/multi-agent/graph_workflow The Graph Workflow API enables you to create and execute complex multi-agent workflows using a directed graph structure. Agents serve as nodes in the graph, and edges define the flow of data and execution between agents. This allows for sophisticated parallel processing, sequential pipelines, and complex multi-layer workflows. Premium: This endpoint is available only on Pro, Ultra, and Premium plans. See Pricing. ## Overview The Graph Workflow API enables you to create and execute complex multi-agent workflows using a directed graph structure. Agents serve as nodes in the graph, and edges define the flow of data and execution between agents. This allows for sophisticated parallel processing, sequential pipelines, and complex multi-layer workflows. **Endpoint:** `POST /v1/graph-workflow/completions` **Base URL:** `https://api.swarms.world` (production) or your custom deployment URL ## Architecture ```mermaid theme={null} flowchart LR E["Entry point"] --> A["Agent A"] A --> B["Agent B"] A --> C["Agent C"] B --> D["Agent D"] C --> D D --> X["End point"] ``` You define the shape yourself: agents are nodes, `edges` are the arrows. Branches run in parallel and rejoin wherever two edges meet the same node. ## Authentication All requests require an API key passed in the `x-api-key` header: ```python theme={null} headers = { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" } ``` ## Input Parameters ### GraphWorkflowInput Schema | Parameter | Type | Required | Default | Description | | -------------- | ---------------------- | -------- | ------- | ----------------------------------------------------------------------- | | `name` | `string` | No | `null` | Unique identifier for the workflow | | `description` | `string` | No | `null` | Detailed description of the workflow's purpose | | `agents` | `List[AgentSpec]` | Yes | - | List of agent specifications to use as nodes in the workflow graph | | `edges` | `List[EdgeSpec\|dict]` | No | `null` | List of edges connecting nodes. Can be EdgeSpec objects or dictionaries | | `entry_points` | `List[string]` | No | `null` | List of node IDs (agent names) that serve as starting points | | `end_points` | `List[string]` | No | `null` | List of node IDs (agent names) that serve as ending points | | `max_loops` | `integer` | No | `1` | Maximum number of execution loops for the workflow | | `task` | `string` | No | `null` | The task to be executed by the workflow | | `img` | `string` | No | `null` | Optional image path/URL for vision-enabled agents | | `auto_compile` | `boolean` | No | `true` | Whether to automatically compile the workflow for optimization | | `verbose` | `boolean` | No | `false` | Whether to enable detailed logging | ### AgentSpec Schema | Parameter | Type | Required | Default | Description | | ----------------------------- | ------------------------ | -------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `agent_name` | `string` | Yes | - | Unique name identifying the agent (used as node ID) | | `description` | `string` | No | `null` | Description of the agent's purpose and capabilities | | `system_prompt` | `string` | No | `null` | Initial instruction or context provided to the agent | | `model_name` | `string` | No | `"claude-sonnet-5"` | AI model to use (e.g., "gpt-4.1", "gpt-4.1-mini", "claude-sonnet-4-20250514") | | `max_tokens` | `integer` | No | `16000` | Maximum number of tokens the agent can generate. Values below 1 are rejected with a 422 validation error | | `temperature` | `float` | No | `null` | Randomness control (lower = more deterministic). If omitted, the provider's own default applies | | `role` | `string` | No | `"worker"` | Agent's role within the swarm | | `max_loops` | `integer \| string` | No | `1` | Maximum number of times the agent can repeat its task, or `"auto"`. Integer values below 1 are rejected with a 422 validation error | | `tools_list_dictionary` | `List[dict]` | No | `null` | List of tools the agent can use | | `selected_tools` | `string \| List[string]` | No | All safe tools | Tools to enable for the autonomous looper when `max_loops="auto"`. Available tools: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. `run_bash` is not permitted | | `mcp_url` | `string` | No | `null` | URL of MCP server for the agent | | `streaming_on` | `boolean` | No | `false` | Whether the agent should stream its output | | `llm_args` | `dict` | No | `null` | Additional LLM arguments (top\_p, frequency\_penalty, etc.) | | `dynamic_temperature_enabled` | `boolean` | No | `false` | Whether to dynamically adjust temperature | | `mcp_config` | `MCPConnection` | No | `null` | MCP connection configuration | | `mcp_configs` | `MultipleMCPConnections` | No | `null` | Multiple MCP connections configuration | | `tool_call_summary` | `boolean` | No | `true` | Whether to summarize tool calls | | `reasoning_effort` | `string` | No | `null` (unset) | Reasoning effort level: `"none"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"ultra"`, or `"max"`. For Claude 5-family models (`claude-sonnet-5`, `claude-opus-5`, `claude-fable-5`) reasoning parameters are currently ignored and the agent runs without extended thinking | | `thinking_tokens` | `integer` | No | `null` | Number of tokens for thinking | | `reasoning_enabled` | `boolean` | No | `false` | Whether to enable reasoning capabilities | ### EdgeSpec Schema | Parameter | Type | Required | Default | Description | | ---------- | -------- | -------- | ------- | ------------------------------------------------------- | | `source` | `string` | Yes | - | Source node ID (agent name) | | `target` | `string` | Yes | - | Target node ID (agent name) | | `metadata` | `dict` | No | `null` | Optional metadata for the edge (custom key-value pairs) | **Edge Format Options:** * Dictionary: `{"source": "Agent1", "target": "Agent2", "metadata": {...}}` * Tuple: `("Agent1", "Agent2")` or `("Agent1", "Agent2", {"metadata": {...}})` * EdgeSpec object: Pydantic EdgeSpec instance ## Output Parameters ### GraphWorkflowOutput Schema | Parameter | Type | Description | | ------------- | -------- | ----------------------------------------------------------- | | `job_id` | `string` | Unique identifier for the workflow execution job | | `name` | `string` | Workflow name from input | | `description` | `string` | Workflow description from input | | `status` | `string` | Execution status ("success" if completed) | | `outputs` | `dict` | Results from all nodes in the workflow, keyed by agent name | | `usage` | `Usage` | Usage statistics including tokens and costs | | `timestamp` | `string` | ISO8601 UTC timestamp when job finished | ### Usage Schema | Parameter | Type | Description | | ---------------- | --------- | ------------------------------------------------------------------------------------- | | `input_tokens` | `integer` | Total number of input tokens consumed | | `output_tokens` | `integer` | Total number of output tokens generated | | `total_tokens` | `integer` | Sum of input and output tokens | | `token_cost` | `float` | Total credits charged for the run: input and output token costs plus `cost_per_agent` | | `cost_per_agent` | `float` | Cost per agent (0.01 \* number\_of\_agents) | ## Cost Calculation Graph Workflow uses unified pricing with agent costs. For detailed pricing information, see the Pricing page. ## Error Responses | Status Code | Description | | ----------- | ------------------------------------------------- | | `400` | Bad Request - Invalid workflow configuration | | `401` | Unauthorized - Invalid or missing API key | | `429` | Too Many Requests - Rate limit exceeded | | `500` | Internal Server Error - Workflow execution failed | ## Examples ### Example 1: Basic Sequential Workflow This example demonstrates a simple two-agent sequential workflow where one agent performs research and another analyzes the results. ```python theme={null} import httpx import os from dotenv import load_dotenv load_dotenv() BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") API_KEY = os.getenv("SWARMS_API_KEY") headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define agents for the workflow agents = [ { "agent_name": "ResearchAgent", "description": "Conducts research on given topics", "system_prompt": "You are an expert researcher. Conduct thorough research and provide comprehensive findings.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "AnalysisAgent", "description": "Analyzes research findings and provides insights", "system_prompt": "You are an expert analyst. Analyze the provided research and extract key insights.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, ] # Define edges - sequential flow: ResearchAgent -> AnalysisAgent edges = [ { "source": "ResearchAgent", "target": "AnalysisAgent", } ] # Create the graph workflow request workflow_input = { "name": "Research-Analysis-Workflow", "description": "A simple sequential workflow for research and analysis", "agents": agents, "edges": edges, "entry_points": ["ResearchAgent"], "end_points": ["AnalysisAgent"], "max_loops": 1, "task": "What are the latest trends in AI development?", "auto_compile": True, "verbose": False, } # Make the request response = httpx.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300.0, ) if response.status_code == 200: result = response.json() print(f"Job ID: {result['job_id']}") print(f"Status: {result['status']}") print(f"\nResearchAgent Output: {result['outputs']['ResearchAgent']}") print(f"AnalysisAgent Output: {result['outputs']['AnalysisAgent']}") print(f"\nUsage:") print(f" Input tokens: {result['usage']['input_tokens']}") print(f" Output tokens: {result['usage']['output_tokens']}") print(f" Total tokens: {result['usage']['total_tokens']}") print(f" Token cost: ${result['usage']['token_cost']:.4f}") else: print(f"Error: {response.status_code}") print(response.text) ``` **Expected Output:** ```json theme={null} { "job_id": "graph-workflow-abc123xyz", "name": "Research-Analysis-Workflow", "description": "A simple sequential workflow for research and analysis", "status": "success", "outputs": { "ResearchAgent": "Research findings on AI trends...", "AnalysisAgent": "Analysis of research findings..." }, "usage": { "input_tokens": 1250, "output_tokens": 3200, "total_tokens": 4450, "token_cost": 0.087325, "cost_per_agent": 0.02 }, "timestamp": "2024-01-15T10:30:45.123456+00:00" } ``` ### Example 2: Parallel Workflow with Multiple Entry Points This example demonstrates a workflow with multiple parallel entry points that converge into a single analysis agent. ```python theme={null} import httpx import os from dotenv import load_dotenv load_dotenv() BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") API_KEY = os.getenv("SWARMS_API_KEY") headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define agents agents = [ { "agent_name": "MarketResearcher", "description": "Researches market trends and opportunities", "system_prompt": "You are a market research expert. Analyze market trends and identify opportunities.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "CompetitorAnalyst", "description": "Analyzes competitor strategies and positioning", "system_prompt": "You are a competitive intelligence expert. Analyze competitor strategies and market positioning.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "TechnologyScout", "description": "Scouts emerging technologies and innovations", "system_prompt": "You are a technology scouting expert. Identify emerging technologies and innovations.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "StrategicSynthesizer", "description": "Synthesizes multiple research streams into strategic insights", "system_prompt": "You are a strategic synthesis expert. Combine multiple research streams into actionable strategic insights.", "model_name": "gpt-4.1", "max_tokens": 6000, "temperature": 0.3, "max_loops": 1, }, ] # Define edges - all three researchers feed into the synthesizer edges = [ {"source": "MarketResearcher", "target": "StrategicSynthesizer"}, {"source": "CompetitorAnalyst", "target": "StrategicSynthesizer"}, {"source": "TechnologyScout", "target": "StrategicSynthesizer"}, ] # Create the workflow request workflow_input = { "name": "Parallel-Research-Synthesis-Workflow", "description": "Parallel research workflow with multiple entry points converging into synthesis", "agents": agents, "edges": edges, "entry_points": ["MarketResearcher", "CompetitorAnalyst", "TechnologyScout"], "end_points": ["StrategicSynthesizer"], "max_loops": 1, "task": "Conduct comprehensive strategic analysis of the AI-powered SaaS market, including market trends, competitor analysis, and emerging technologies", "auto_compile": True, "verbose": False, } # Make the request response = httpx.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=600.0, ) if response.status_code == 200: result = response.json() print(f"Job ID: {result['job_id']}") print(f"Status: {result['status']}") print(f"\nOutputs:") for agent_name in ["MarketResearcher", "CompetitorAnalyst", "TechnologyScout", "StrategicSynthesizer"]: if agent_name in result['outputs']: output_preview = str(result['outputs'][agent_name])[:200] print(f" {agent_name}: {output_preview}...") print(f"\nUsage:") print(f" Input tokens: {result['usage']['input_tokens']}") print(f" Output tokens: {result['usage']['output_tokens']}") print(f" Total tokens: {result['usage']['total_tokens']}") print(f" Token cost: ${result['usage']['token_cost']:.4f}") print(f" Cost per agent: ${result['usage']['cost_per_agent']:.4f}") else: print(f"Error: {response.status_code}") print(response.text) ``` **Expected Output:** ```json theme={null} { "job_id": "graph-workflow-def456uvw", "name": "Parallel-Research-Synthesis-Workflow", "description": "Parallel research workflow with multiple entry points converging into synthesis", "status": "success", "outputs": { "MarketResearcher": "Market analysis findings...", "CompetitorAnalyst": "Competitor analysis findings...", "TechnologyScout": "Technology scouting findings...", "StrategicSynthesizer": "Synthesized strategic insights combining all research streams..." }, "usage": { "input_tokens": 3800, "output_tokens": 8500, "total_tokens": 12300, "token_cost": 0.22195, "cost_per_agent": 0.04 }, "timestamp": "2024-01-15T10:35:20.456789+00:00" } ``` ### Example 3: Complex Multi-Layer Workflow This example demonstrates a sophisticated three-layer workflow with data collection, analysis, validation, and synthesis stages. ```python theme={null} import httpx import os from dotenv import load_dotenv load_dotenv() BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") API_KEY = os.getenv("SWARMS_API_KEY") headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define agents for different stages agents = [ # Layer 1: Data Collectors { "agent_name": "DataCollector1", "description": "Collects data from source 1", "system_prompt": "You are a data collector. Gather comprehensive data from your assigned source.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "DataCollector2", "description": "Collects data from source 2", "system_prompt": "You are a data collector. Gather comprehensive data from your assigned source.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "DataCollector3", "description": "Collects data from source 3", "system_prompt": "You are a data collector. Gather comprehensive data from your assigned source.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, # Layer 2: Analysts { "agent_name": "Analyst1", "description": "Performs analysis on collected data", "system_prompt": "You are an analyst. Analyze the provided data and extract key insights.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "Analyst2", "description": "Performs analysis on collected data", "system_prompt": "You are an analyst. Analyze the provided data and extract key insights.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "Analyst3", "description": "Performs analysis on collected data", "system_prompt": "You are an analyst. Analyze the provided data and extract key insights.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, # Layer 3: Validators { "agent_name": "Validator1", "description": "Validates analysis results", "system_prompt": "You are a validator. Review and validate the provided analysis for accuracy and completeness.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "Validator2", "description": "Validates analysis results", "system_prompt": "You are a validator. Review and validate the provided analysis for accuracy and completeness.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, # Final Layer: Synthesis { "agent_name": "SynthesisAgent", "description": "Synthesizes all validated results", "system_prompt": "You are a synthesis expert. Combine all validated analyses into a comprehensive final report.", "model_name": "gpt-4.1", "max_tokens": 6000, "temperature": 0.3, "max_loops": 1, }, ] # Define edges creating a complex multi-layer structure # Layer 1 -> Layer 2: All collectors feed all analysts (parallel chain) # Layer 2 -> Layer 3: All analysts feed validators # Layer 3 -> Final: All validators feed synthesis agent edges = [ # Layer 1 -> Layer 2: Parallel chain pattern {"source": "DataCollector1", "target": "Analyst1"}, {"source": "DataCollector1", "target": "Analyst2"}, {"source": "DataCollector1", "target": "Analyst3"}, {"source": "DataCollector2", "target": "Analyst1"}, {"source": "DataCollector2", "target": "Analyst2"}, {"source": "DataCollector2", "target": "Analyst3"}, {"source": "DataCollector3", "target": "Analyst1"}, {"source": "DataCollector3", "target": "Analyst2"}, {"source": "DataCollector3", "target": "Analyst3"}, # Layer 2 -> Layer 3: Analysts feed validators {"source": "Analyst1", "target": "Validator1"}, {"source": "Analyst2", "target": "Validator1"}, {"source": "Analyst3", "target": "Validator1"}, {"source": "Analyst1", "target": "Validator2"}, {"source": "Analyst2", "target": "Validator2"}, {"source": "Analyst3", "target": "Validator2"}, # Layer 3 -> Final: Validators feed synthesis {"source": "Validator1", "target": "SynthesisAgent"}, {"source": "Validator2", "target": "SynthesisAgent"}, ] # Create the graph workflow request workflow_input = { "name": "Complex-Multi-Layer-Workflow", "description": "Complex multi-layer workflow with data collection, analysis, validation, and synthesis", "agents": agents, "edges": edges, "entry_points": ["DataCollector1", "DataCollector2", "DataCollector3"], "end_points": ["SynthesisAgent"], "max_loops": 1, "task": "Conduct comprehensive research on renewable energy markets including data collection, multi-perspective analysis, validation, and final synthesis", "auto_compile": True, "verbose": True, } # Make the request response = httpx.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=900.0, # 15 minute timeout for complex workflows ) if response.status_code == 200: result = response.json() print(f"Job ID: {result['job_id']}") print(f"Status: {result['status']}") print(f"\nFinal synthesis output:") outputs = result.get("outputs", {}) if "SynthesisAgent" in outputs: print(f" {outputs['SynthesisAgent']}") print(f"\nUsage:") usage = result.get("usage", {}) print(f" Input tokens: {usage.get('input_tokens', 0)}") print(f" Output tokens: {usage.get('output_tokens', 0)}") print(f" Total tokens: {usage.get('total_tokens', 0)}") print(f" Token cost: ${usage.get('token_cost', 0):.4f}") print(f" Cost per agent: ${usage.get('cost_per_agent', 0):.4f}") else: print(f"Error: {response.status_code}") print(response.text) ``` **Expected Output:** ```json theme={null} { "job_id": "graph-workflow-ghi789rst", "name": "Complex-Multi-Layer-Workflow", "description": "Complex multi-layer workflow with data collection, analysis, validation, and synthesis", "status": "success", "outputs": { "DataCollector1": "Data collection results from source 1...", "DataCollector2": "Data collection results from source 2...", "DataCollector3": "Data collection results from source 3...", "Analyst1": "Analysis results from analyst 1...", "Analyst2": "Analysis results from analyst 2...", "Analyst3": "Analysis results from analyst 3...", "Validator1": "Validation results from validator 1...", "Validator2": "Validation results from validator 2...", "SynthesisAgent": "Comprehensive synthesis combining all validated analyses..." }, "usage": { "input_tokens": 12000, "output_tokens": 25000, "total_tokens": 37000, "token_cost": 0.6305, "cost_per_agent": 0.09 }, "timestamp": "2024-01-15T10:40:15.789012+00:00" } ``` ### Example 4: Workflow with Edge Metadata This example demonstrates how to use custom metadata on edges to provide additional context and configuration. ```python theme={null} import httpx import os from dotenv import load_dotenv load_dotenv() BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") API_KEY = os.getenv("SWARMS_API_KEY") headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define agents with specific roles agents = [ { "agent_name": "ResearchAgent", "description": "Conducts research on given topics", "system_prompt": "You are an expert researcher. Conduct thorough research and provide comprehensive findings.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "AnalysisAgent", "description": "Analyzes research findings and provides insights", "system_prompt": "You are an expert analyst. Analyze the provided research and extract key insights.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "ReportGenerator", "description": "Generates final reports", "system_prompt": "You are a report generation expert. Create comprehensive, well-structured reports.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, ] # Define edges with custom metadata edges = [ { "source": "ResearchAgent", "target": "AnalysisAgent", "metadata": { "data_type": "research_findings", "priority": "high", "timeout": 300, "retry_on_failure": True, }, }, { "source": "AnalysisAgent", "target": "ReportGenerator", "metadata": { "data_type": "analysis_results", "priority": "high", "format": "structured", }, }, ] # Create the graph workflow request workflow_input = { "name": "Metadata-Workflow", "description": "Workflow demonstrating metadata usage on edges", "agents": agents, "edges": edges, "entry_points": ["ResearchAgent"], "end_points": ["ReportGenerator"], "max_loops": 1, "task": "Research and analyze the impact of climate change on agriculture, then generate a comprehensive report", "auto_compile": True, "verbose": False, } # Make the request response = httpx.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300.0, ) if response.status_code == 200: result = response.json() print(f"Job ID: {result['job_id']}") print(f"Status: {result['status']}") print(f"\nOutputs:") outputs = result.get("outputs", {}) for agent_name in ["ResearchAgent", "AnalysisAgent", "ReportGenerator"]: if agent_name in outputs: output_preview = str(outputs[agent_name])[:150] print(f" {agent_name}: {output_preview}...") print(f"\nUsage:") usage = result.get("usage", {}) print(f" Input tokens: {usage.get('input_tokens', 0)}") print(f" Output tokens: {usage.get('output_tokens', 0)}") print(f" Total tokens: {usage.get('total_tokens', 0)}") print(f" Token cost: ${usage.get('token_cost', 0):.4f}") print(f" Cost per agent: ${usage.get('cost_per_agent', 0):.4f}") else: print(f"Error: {response.status_code}") print(response.text) ``` **Expected Output:** ```json theme={null} { "job_id": "graph-workflow-jkl012mno", "name": "Metadata-Workflow", "description": "Workflow demonstrating metadata usage on edges", "status": "success", "outputs": { "ResearchAgent": "Research findings on climate change impact on agriculture...", "AnalysisAgent": "Analysis of research findings with key insights...", "ReportGenerator": "Comprehensive report on climate change and agriculture..." }, "usage": { "input_tokens": 2100, "output_tokens": 4800, "total_tokens": 6900, "token_cost": 0.13245, "cost_per_agent": 0.03 }, "timestamp": "2024-01-15T10:45:30.345678+00:00" } ``` ### Example 5: Async Workflow with Vision Support This example demonstrates an asynchronous workflow request with image input for vision-enabled agents. ```python theme={null} import httpx import asyncio import os from dotenv import load_dotenv load_dotenv() BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") API_KEY = os.getenv("SWARMS_API_KEY") headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } async def run_vision_workflow(): """Example of using Graph Workflow with vision/image support""" # Define agents with vision capabilities agents = [ { "agent_name": "ImageAnalyzer", "description": "Analyzes images and extracts visual information", "system_prompt": "You are an expert image analyst. Analyze images and extract detailed visual information.", "model_name": "gpt-4.1", # Vision-capable model "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "ContentGenerator", "description": "Generates content based on image analysis", "system_prompt": "You are a content generation expert. Create engaging content based on image analysis.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.5, "max_loops": 1, }, { "agent_name": "QualityReviewer", "description": "Reviews and validates generated content", "system_prompt": "You are a quality reviewer. Review content for accuracy, clarity, and engagement.", "model_name": "gpt-4.1", "max_tokens": 3000, "temperature": 0.2, "max_loops": 1, }, ] # Define edges edges = [ {"source": "ImageAnalyzer", "target": "ContentGenerator"}, {"source": "ContentGenerator", "target": "QualityReviewer"}, ] # Create the workflow request with image workflow_input = { "name": "Vision-Content-Workflow", "description": "Workflow for analyzing images and generating content", "agents": agents, "edges": edges, "entry_points": ["ImageAnalyzer"], "end_points": ["QualityReviewer"], "max_loops": 1, "task": "Analyze this image and generate engaging social media content about it", "img": "https://example.com/image.jpg", # Image URL or path "auto_compile": True, "verbose": False, } try: async with httpx.AsyncClient(timeout=600.0) as client: response = await client.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, ) if response.status_code == 200: result = response.json() print(f"Job ID: {result['job_id']}") print(f"Status: {result['status']}") print(f"\nOutputs:") outputs = result.get("outputs", {}) for agent_name in ["ImageAnalyzer", "ContentGenerator", "QualityReviewer"]: if agent_name in outputs: output_preview = str(outputs[agent_name])[:200] print(f" {agent_name}: {output_preview}...") print(f"\nUsage:") usage = result.get("usage", {}) print(f" Input tokens: {usage.get('input_tokens', 0)}") print(f" Output tokens: {usage.get('output_tokens', 0)}") print(f" Total tokens: {usage.get('total_tokens', 0)}") print(f" Token cost: ${usage.get('token_cost', 0):.4f}") print(f" Cost per agent: ${usage.get('cost_per_agent', 0):.4f}") return result else: print(f"Error: {response.status_code}") print(response.text) return {"error": response.status_code, "response": response.text} except httpx.TimeoutException: print("Request timed out. Vision workflows can take several minutes.") return {"error": "Request timed out"} except httpx.RequestError as e: print(f"Network error: {e}") return {"error": f"Network error: {e}"} except Exception as e: print(f"Unexpected error: {e}") return {"error": f"Unexpected error: {e}"} if __name__ == "__main__": asyncio.run(run_vision_workflow()) ``` **Expected Output:** ```json theme={null} { "job_id": "graph-workflow-pqr345stu", "name": "Vision-Content-Workflow", "description": "Workflow for analyzing images and generating content", "status": "success", "outputs": { "ImageAnalyzer": "Detailed analysis of the image including visual elements, composition, and key features...", "ContentGenerator": "Engaging social media content based on the image analysis...", "QualityReviewer": "Quality review confirming content accuracy and engagement..." }, "usage": { "input_tokens": 3500, "output_tokens": 4200, "total_tokens": 7700, "token_cost": 0.13045, "cost_per_agent": 0.03 }, "timestamp": "2024-01-15T10:50:45.567890+00:00" } ``` ## Best Practices 1. **Agent Naming:** Use descriptive, unique names for agents as they serve as node identifiers in the graph. 2. **Entry and End Points:** Always specify `entry_points` and `end_points` to ensure predictable workflow execution. 3. **Edge Definitions:** Ensure all edges reference valid agent names. The source and target must match `agent_name` values. 4. **Timeout Configuration:** Set appropriate timeouts based on workflow complexity: * Simple workflows: 300 seconds (5 minutes) * Medium workflows: 600 seconds (10 minutes) * Complex workflows: 900+ seconds (15+ minutes) 5. **Error Handling:** Always check response status codes and handle errors appropriately. Use try-except blocks for network errors. 6. **Token Management:** Monitor token usage through the `usage` field in responses to optimize costs and stay within limits. 7. **Model Selection:** Choose appropriate models based on task requirements: * For vision tasks: Use vision-capable models like `gpt-4.1` * For complex reasoning: Use models like `claude-sonnet-4-20250514` * For cost efficiency: Use `gpt-4.1-mini` for simpler tasks 8. **Workflow Compilation:** Keep `auto_compile` enabled (default) for optimal performance, unless you need to debug workflow structure. 9. **Parallel Execution:** Design workflows with multiple entry points to leverage parallel execution capabilities. 10. **Metadata Usage:** Use edge metadata to provide additional context or configuration that can be used by custom workflow logic. ## Rate Limits Rate limits are enforced per API key and subscription tier: * **Free Tier:** 100 requests per minute, 350 requests per hour, 1,200 requests per day * **Premium Tier:** 2,000 requests per minute, 10,000 requests per hour, 100,000 requests per day Rate limit information is returned in response headers: * `X-RateLimit-Limit-Minute`: Requests allowed per minute * `X-RateLimit-Remaining-Minute`: Requests remaining in the current minute * `X-RateLimit-Limit-Day`: Requests allowed per day * `X-RateLimit-Remaining-Day`: Requests remaining today * `X-RateLimit-Reset`: Unix timestamp when the minute window resets * `X-RateLimit-Tier`: Your current tier (`free` or `premium`) ## Support For additional support, examples, and updates: * Check the main documentation: [Swarms API Documentation](https://docs.swarms.ai) * Review example code in the `examples/multi_agent/graph_workflow/` directory * Contact support through your Swarms dashboard # GroupChat Source: https://docs.swarms.ai/docs/documentation/multi-agent/group_chat Collaborative discussion swarm where multiple agents engage in group conversation, building on each other's ideas for brainstorming and cross-functional planning **Swarm Type**: `GroupChat` ## Overview The GroupChat swarm type facilitates collaborative discussion between multiple specialist agents. Unlike workflows where agents operate independently, GroupChat enables agents to engage in a shared conversation where each participant can build on, challenge, and refine ideas from others. This architecture is ideal for brainstorming, cross-functional planning, and problems that benefit from interactive dialogue. Key features: * **Collaborative Discussion**: Agents engage in shared conversation rather than working in isolation * **Cross-Functional Input**: Combine perspectives from different domains in a single discussion * **Idea Building**: Each agent can react to and build on contributions from other participants * **Convergent Outcomes**: Discussion naturally converges toward actionable conclusions ## Architecture ```mermaid theme={null} flowchart TD T["Task"] --> C["Shared conversation"] C <--> A["Agent A"] C <--> B["Agent B"] C <--> D["Agent C"] C --> O["Conclusion"] ``` Unlike the workflow types, agents talk to each other. Every contribution lands in one shared transcript that the others can build on or push back against. ## Use Cases * Product strategy brainstorming sessions * Cross-functional planning and alignment * Architectural design discussions * Risk assessment with multiple stakeholders * Creative ideation requiring diverse perspectives ## API Usage ### Basic GroupChat Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Product Launch Strategy", "description": "Cross-functional product launch discussion", "swarm_type": "GroupChat", "task": "Discuss and develop a go-to-market strategy for an AI-powered project management tool targeting remote engineering teams of 5-30 people. The MVP is built with 12 beta users. Budget is $50K with an 8-week timeline to public launch.", "agents": [ { "agent_name": "Product Manager", "description": "Drives product vision, roadmap, and prioritization", "system_prompt": "You are a Senior Product Manager. Define the core value proposition and target personas. Prioritize features for the launch MVP. Identify key metrics and success criteria. Be concise and action-oriented. Build on what other participants say.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a Growth Marketing Lead. Propose acquisition channels ranked by expected ROI. Design the launch campaign strategy. Suggest pricing and positioning tactics. Be data-driven and specific with numbers.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Engineering Lead", "description": "Assesses technical feasibility and delivery timelines", "system_prompt": "You are an Engineering Lead. Evaluate technical feasibility of proposed features. Flag complexity risks and dependencies. Propose a realistic MVP scope and timeline. Be pragmatic and push back on scope creep.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Customer Success Lead", "description": "Represents the customer voice and retention strategy", "system_prompt": "You are a Customer Success Lead. Advocate for the end-user experience. Identify onboarding friction points. Propose retention and engagement hooks. Ground the discussion in real customer needs.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Product Launch Strategy", "description": "Cross-functional product launch discussion", "swarm_type": "GroupChat", "task": "Discuss and develop a go-to-market strategy for an AI-powered project management tool targeting remote engineering teams of 5-30 people. The MVP is built with 12 beta users. Budget is $50K with an 8-week timeline to public launch.", "agents": [ { "agent_name": "Product Manager", "description": "Drives product vision, roadmap, and prioritization", "system_prompt": "You are a Senior Product Manager. Define the core value proposition and target personas. Prioritize features for the launch MVP. Identify key metrics and success criteria. Be concise and action-oriented. Build on what other participants say.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a Growth Marketing Lead. Propose acquisition channels ranked by expected ROI. Design the launch campaign strategy. Suggest pricing and positioning tactics. Be data-driven and specific with numbers.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Engineering Lead", "description": "Assesses technical feasibility and delivery timelines", "system_prompt": "You are an Engineering Lead. Evaluate technical feasibility of proposed features. Flag complexity risks and dependencies. Propose a realistic MVP scope and timeline. Be pragmatic and push back on scope creep.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Customer Success Lead", "description": "Represents the customer voice and retention strategy", "system_prompt": "You are a Customer Success Lead. Advocate for the end-user experience. Identify onboarding friction points. Propose retention and engagement hooks. Ground the discussion in real customer needs.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("GroupChat swarm completed successfully!") for output in result.get("output", []): print(f"\n{output['role']}: {output['content'][:200]}...") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Product Launch Strategy", description: "Cross-functional product launch discussion", swarm_type: "GroupChat", task: "Discuss and develop a go-to-market strategy for an AI-powered project management tool targeting remote engineering teams of 5-30 people. The MVP is built with 12 beta users. Budget is $50K with an 8-week timeline to public launch.", agents: [ { agent_name: "Product Manager", description: "Drives product vision, roadmap, and prioritization", system_prompt: "You are a Senior Product Manager. Define the core value proposition and target personas. Prioritize features for the launch MVP. Identify key metrics and success criteria. Be concise and action-oriented. Build on what other participants say.", model_name: "gpt-4.1", role: "worker", max_loops: 1, temperature: 0.5 }, { agent_name: "Growth Marketer", description: "Designs acquisition channels and launch campaigns", system_prompt: "You are a Growth Marketing Lead. Propose acquisition channels ranked by expected ROI. Design the launch campaign strategy. Suggest pricing and positioning tactics. Be data-driven and specific with numbers.", model_name: "gpt-4.1", role: "worker", max_loops: 1, temperature: 0.5 }, { agent_name: "Engineering Lead", description: "Assesses technical feasibility and delivery timelines", system_prompt: "You are an Engineering Lead. Evaluate technical feasibility of proposed features. Flag complexity risks and dependencies. Propose a realistic MVP scope and timeline. Be pragmatic and push back on scope creep.", model_name: "gpt-4.1", role: "worker", max_loops: 1, temperature: 0.4 }, { agent_name: "Customer Success Lead", description: "Represents the customer voice and retention strategy", system_prompt: "You are a Customer Success Lead. Advocate for the end-user experience. Identify onboarding friction points. Propose retention and engagement hooks. Ground the discussion in real customer needs.", model_name: "gpt-4.1", role: "worker", max_loops: 1, temperature: 0.5 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("GroupChat swarm completed successfully!"); result.output.forEach(output => { console.log(`\n${output.role}: ${output.content}`); }); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` Role string `json:"role"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Product Launch Strategy", Description: "Cross-functional product launch discussion", SwarmType: "GroupChat", Task: "Discuss and develop a go-to-market strategy for an AI-powered project management tool targeting remote engineering teams of 5-30 people. The MVP is built with 12 beta users. Budget is $50K with an 8-week timeline to public launch.", Agents: []Agent{ { AgentName: "Product Manager", Description: "Drives product vision, roadmap, and prioritization", SystemPrompt: "You are a Senior Product Manager. Define the core value proposition and target personas. Prioritize features for the launch MVP. Identify key metrics and success criteria. Be concise and action-oriented. Build on what other participants say.", ModelName: "gpt-4.1", Role: "worker", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Growth Marketer", Description: "Designs acquisition channels and launch campaigns", SystemPrompt: "You are a Growth Marketing Lead. Propose acquisition channels ranked by expected ROI. Design the launch campaign strategy. Suggest pricing and positioning tactics. Be data-driven and specific with numbers.", ModelName: "gpt-4.1", Role: "worker", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Engineering Lead", Description: "Assesses technical feasibility and delivery timelines", SystemPrompt: "You are an Engineering Lead. Evaluate technical feasibility of proposed features. Flag complexity risks and dependencies. Propose a realistic MVP scope and timeline. Be pragmatic and push back on scope creep.", ModelName: "gpt-4.1", Role: "worker", MaxLoops: 1, Temperature: 0.4, }, { AgentName: "Customer Success Lead", Description: "Represents the customer voice and retention strategy", SystemPrompt: "You are a Customer Success Lead. Advocate for the end-user experience. Identify onboarding friction points. Propose retention and engagement hooks. Ground the discussion in real customer needs.", ModelName: "gpt-4.1", Role: "worker", MaxLoops: 1, Temperature: 0.5, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Product Launch Strategy", "description": "Cross-functional product launch discussion", "swarm_type": "GroupChat", "task": "Discuss and develop a go-to-market strategy for an AI-powered project management tool targeting remote engineering teams of 5-30 people. The MVP is built with 12 beta users. Budget is $50K with an 8-week timeline to public launch.", "agents": [ { "agent_name": "Product Manager", "description": "Drives product vision, roadmap, and prioritization", "system_prompt": "You are a Senior Product Manager. Define the core value proposition and target personas. Prioritize features for the launch MVP. Identify key metrics and success criteria. Be concise and action-oriented. Build on what other participants say.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a Growth Marketing Lead. Propose acquisition channels ranked by expected ROI. Design the launch campaign strategy. Suggest pricing and positioning tactics. Be data-driven and specific with numbers.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Engineering Lead", "description": "Assesses technical feasibility and delivery timelines", "system_prompt": "You are an Engineering Lead. Evaluate technical feasibility of proposed features. Flag complexity risks and dependencies. Propose a realistic MVP scope and timeline. Be pragmatic and push back on scope creep.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Customer Success Lead", "description": "Represents the customer voice and retention strategy", "system_prompt": "You are a Customer Success Lead. Advocate for the end-user experience. Identify onboarding friction points. Propose retention and engagement hooks. Ground the discussion in real customer needs.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("GroupChat swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-G17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Product Launch Strategy", "description": "Cross-functional product launch discussion", "swarm_type": "GroupChat", "output": [ { "role": "Product Manager", "content": "Here's my take on the launch strategy. Value proposition: 'Stop managing tasks — let AI manage them for you.' Target persona: engineering managers at remote-first startups who currently use Jira or Linear but struggle with sprint planning accuracy. MVP priority for launch: (1) AI task assignment — this is the core differentiator, (2) Slack integration — lowest friction adoption path, (3) standup summaries — immediate daily value. I'd defer Jira migration and delivery risk prediction post-launch. Success metrics: 50 teams onboarded in 8 weeks, 60% WAU after first month." }, { "role": "Growth Marketer", "content": "Love the positioning. Channel strategy for the $50K budget: Product Hunt launch ($2K, expected 500-1K signups), dev-focused content marketing ($15K), Slack community partnerships ($8K), LinkedIn ads targeting eng managers ($15K, est. CAC $35-50), and a beta user referral program ($10K). Pricing: free tier up to 5 users as growth loop, Pro at $12/user/month targeting ~$2,500 ACV, with a 40% launch discount on annual plans for the first 3 months." }, { "role": "Engineering Lead", "content": "Reality check on scope. Feasible in 8 weeks: AI task assignment (core algo exists, needs polish — 3 weeks), Slack integration (standard OAuth + webhooks — 2 weeks), standup summaries (v1 using activity logs — 1 week). Risks: GitHub integration adds 2-3 weeks for bidirectional sync, recommend starting with read-only status sync (1 week). AI assignment accuracy has a cold-start problem for new teams — suggest manual override plus learning mode. Timeline: 6 weeks eng + 2 weeks buffer, doable if we freeze scope now." }, { "role": "Customer Success Lead", "content": "From our 12 beta users, top onboarding friction: teams don't trust AI assignments on day one (need a suggestion mode before autonomous mode), Slack connection takes 3 clicks but users expect 1-click, and there's no clear aha moment in the first 5 minutes. Retention hooks I'd prioritize: daily standup digest in Slack (passive value), weekly time-saved report (quantifies ROI for the buyer), team leaderboard for sprint completion. Common objection: 'How is this different from Jira automation rules?' — we need a comparison page and a 2-minute demo video." } ], "number_of_agents": 4, "execution_time": 35.2, "usage": { "input_tokens": 45, "output_tokens": 2400, "total_tokens": 2445, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.000293, "output_token_cost": 0.0444, "token_counts": { "total_input_tokens": 45, "total_output_tokens": 2400, "total_tokens": 2445 }, "num_agents": 4, "night_time_discount_applied": false }, "total_cost": 0.084693, "discount_active": false, "discount_type": "none", "discount_percentage": 0 } } } ``` ## Best Practices * Design agents with complementary but distinct expertise to maximize discussion breadth * Use descriptive system prompts that instruct agents to build on and react to other participants' input * GroupChat works best with 3-6 agents — too few limits perspective diversity, too many dilutes focus * Ideal for brainstorming and planning tasks where interactive dialogue adds more value than independent analysis # HeavySwarm Source: https://docs.swarms.ai/docs/documentation/multi-agent/heavy_swarm High-capacity multi-agent swarm that decomposes complex tasks into specialized questions and executes them using five specialized agents for comprehensive analysis **Swarm Type**: `HeavySwarm` ## Overview The HeavySwarm is a sophisticated multi-agent orchestration system inspired by X.AI's Grok 4 Heavy architecture. It automatically decomposes complex tasks into specialized questions and executes them using five built-in specialized agents: Research, Analysis, Alternatives, Verification, and Synthesis. Unlike other swarm types, HeavySwarm creates and manages its own agents internally — pass an empty `agents` array (`"agents": []`) in the request. Key features: * **Automatic Task Decomposition**: Complex tasks are intelligently broken down into specialized questions using function calling * **Five Specialized Agents**: Research, Analysis, Alternatives, Verification, and Synthesis agents work in concert * **Parallel Execution**: Four specialist agents execute simultaneously for maximum efficiency * **Iterative Refinement**: Multi-loop execution where each loop builds upon previous results * **Comprehensive Synthesis**: A dedicated synthesis agent integrates all findings into an executive-ready report ## Architecture ```mermaid theme={null} flowchart TD T["Task"] --> Q["Question agent writes 4 questions"] Q --> R["Research"] Q --> A["Analysis"] Q --> L["Alternatives"] Q --> V["Verification"] R --> S["Synthesis agent"] A --> S L --> S V --> S S --> O["Report"] S -.->|"next loop"| Q ``` The HeavySwarm follows a structured 5-phase workflow: 1. **Task Decomposition** — A question generation agent analyzes the input task and creates four specialized questions using function calling 2. **Parallel Execution** — Four specialized agents (Research, Analysis, Alternatives, Verification) execute their questions simultaneously 3. **Result Collection** — Outputs are validated and collected from all agents 4. **Synthesis** — A fifth Synthesis agent integrates all results into a comprehensive report 5. **Iterative Refinement** — When `heavy_swarm_max_loops` > 1, the process repeats with context from previous iterations ### Specialized Agents | Agent | Role | | ---------------------- | ----------------------------------------------------------------------------------------------------------- | | **Research Agent** | Comprehensive information gathering, source verification, data collection, and systematic search strategies | | **Analysis Agent** | Statistical analysis, pattern recognition, causal relationship identification, and predictive modeling | | **Alternatives Agent** | Strategic option generation, creative problem-solving, scenario planning, and trade-off analysis | | **Verification Agent** | Fact-checking, feasibility assessment, risk assessment, and compliance verification | | **Synthesis Agent** | Multi-perspective integration, executive summaries, strategic alignment, and actionable recommendations | ## HeavySwarm-Specific Parameters Since HeavySwarm manages its own agents, it uses dedicated parameters at the swarm configuration level: | Parameter | Type | Default | Description | | --------------------------------------- | --------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- | | `heavy_swarm_max_loops` | `integer` | `1` | Number of execution loops per agent. Higher values enable iterative refinement for deeper analysis. | | `heavy_swarm_question_agent_model_name` | `string` | `"gpt-4.1"` | Model used for the question generation phase. This agent decomposes the task into specialized questions. | | `heavy_swarm_worker_model_name` | `string` | `"claude-sonnet-4-20250514"` | Model used for all five specialized worker agents (Research, Analysis, Alternatives, Verification, Synthesis). | | `heavy_swarm_variant` | `string` | `"default"` | Which agent variant to run. One of `"default"`, `"medium"`, or `"heavy"`. | ## Use Cases * Deep research and comprehensive market analysis * Due diligence and investment research * Policy analysis and strategic planning * Technology assessment and competitive intelligence * Complex problem-solving requiring multiple perspectives * Medical or scientific research synthesis ## API Usage ### Basic HeavySwarm Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Market Research Swarm", "description": "Comprehensive market analysis using HeavySwarm", "swarm_type": "HeavySwarm", "task": "Analyze the current state and future outlook of the renewable energy sector, including market trends, key players, investment opportunities, regulatory landscape, and technological innovations", "agents": [], "heavy_swarm_max_loops": 1, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Market Research Swarm", "description": "Comprehensive market analysis using HeavySwarm", "swarm_type": "HeavySwarm", "task": "Analyze the current state and future outlook of the renewable energy sector, including market trends, key players, investment opportunities, regulatory landscape, and technological innovations", "agents": [], "heavy_swarm_max_loops": 1, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print(json.dumps(result["output"], indent=2)) else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Market Research Swarm", description: "Comprehensive market analysis using HeavySwarm", swarm_type: "HeavySwarm", task: "Analyze the current state and future outlook of the renewable energy sector, including market trends, key players, investment opportunities, regulatory landscape, and technological innovations", agents: [], heavy_swarm_max_loops: 1, heavy_swarm_question_agent_model_name: "gpt-4.1", heavy_swarm_worker_model_name: "claude-sonnet-4-20250514", max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("HeavySwarm completed successfully!"); console.log("Output:", JSON.stringify(result.output, null, 2)); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []interface{} `json:"agents"` HeavySwarmMaxLoops int `json:"heavy_swarm_max_loops"` HeavySwarmQuestionAgentModel string `json:"heavy_swarm_question_agent_model_name"` HeavySwarmWorkerModel string `json:"heavy_swarm_worker_model_name"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Market Research Swarm", Description: "Comprehensive market analysis using HeavySwarm", SwarmType: "HeavySwarm", Task: "Analyze the current state and future outlook of the renewable energy sector, including market trends, key players, investment opportunities, regulatory landscape, and technological innovations", Agents: []interface{}{}, HeavySwarmMaxLoops: 1, HeavySwarmQuestionAgentModel: "gpt-4.1", HeavySwarmWorkerModel: "claude-sonnet-4-20250514", MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Market Research Swarm", "description": "Comprehensive market analysis using HeavySwarm", "swarm_type": "HeavySwarm", "task": "Analyze the current state and future outlook of the renewable energy sector, including market trends, key players, investment opportunities, regulatory landscape, and technological innovations", "agents": [], "heavy_swarm_max_loops": 1, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("HeavySwarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` ### Multi-Loop Deep Analysis Example Use multiple loops for iterative refinement where each loop builds upon the previous results: ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Deep Due Diligence Swarm", "description": "Multi-loop investment due diligence analysis", "swarm_type": "HeavySwarm", "task": "Conduct a comprehensive due diligence analysis on the AI semiconductor industry, evaluating NVIDIA, AMD, and Intel as investment opportunities. Assess financial health, competitive positioning, supply chain risks, and 5-year growth projections", "agents": [], "heavy_swarm_max_loops": 3, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 2 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Deep Due Diligence Swarm", "description": "Multi-loop investment due diligence analysis", "swarm_type": "HeavySwarm", "task": "Conduct a comprehensive due diligence analysis on the AI semiconductor industry, evaluating NVIDIA, AMD, and Intel as investment opportunities. Assess financial health, competitive positioning, supply chain risks, and 5-year growth projections", "agents": [], "heavy_swarm_max_loops": 3, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 2 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print(json.dumps(result["output"], indent=2)) else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Deep Due Diligence Swarm", description: "Multi-loop investment due diligence analysis", swarm_type: "HeavySwarm", task: "Conduct a comprehensive due diligence analysis on the AI semiconductor industry, evaluating NVIDIA, AMD, and Intel as investment opportunities. Assess financial health, competitive positioning, supply chain risks, and 5-year growth projections", agents: [], heavy_swarm_max_loops: 3, heavy_swarm_question_agent_model_name: "gpt-4.1", heavy_swarm_worker_model_name: "claude-sonnet-4-20250514", max_loops: 2 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("Deep analysis completed!"); console.log("Output:", JSON.stringify(result.output, null, 2)); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []interface{} `json:"agents"` HeavySwarmMaxLoops int `json:"heavy_swarm_max_loops"` HeavySwarmQuestionAgentModel string `json:"heavy_swarm_question_agent_model_name"` HeavySwarmWorkerModel string `json:"heavy_swarm_worker_model_name"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Deep Due Diligence Swarm", Description: "Multi-loop investment due diligence analysis", SwarmType: "HeavySwarm", Task: "Conduct a comprehensive due diligence analysis on the AI semiconductor industry, evaluating NVIDIA, AMD, and Intel as investment opportunities. Assess financial health, competitive positioning, supply chain risks, and 5-year growth projections", Agents: []interface{}{}, HeavySwarmMaxLoops: 3, HeavySwarmQuestionAgentModel: "gpt-4.1", HeavySwarmWorkerModel: "claude-sonnet-4-20250514", MaxLoops: 2, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Deep Due Diligence Swarm", "description": "Multi-loop investment due diligence analysis", "swarm_type": "HeavySwarm", "task": "Conduct a comprehensive due diligence analysis on the AI semiconductor industry, evaluating NVIDIA, AMD, and Intel as investment opportunities. Assess financial health, competitive positioning, supply chain risks, and 5-year growth projections", "agents": [], "heavy_swarm_max_loops": 3, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": 2 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("Deep analysis completed!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-K29xMFDrsmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Market Research Swarm", "description": "Comprehensive market analysis using HeavySwarm", "swarm_type": "HeavySwarm", "output": [ { "role": "Question Generator Agent", "content": { "research_question": "What are the current global market size, growth rates, and key players across solar, wind, hydrogen, and battery storage segments?", "analysis_question": "What statistical patterns emerge from renewable energy adoption rates, cost curves, and capacity factor improvements over the past decade?", "alternatives_question": "What are the most promising investment strategies across renewable energy subsectors considering risk-adjusted returns and portfolio diversification?", "verification_question": "How do projected renewable energy cost trajectories and policy commitments align with independently verified deployment data and grid integration feasibility?" } }, { "role": "Research-Agent", "content": "Comprehensive research findings on the renewable energy sector including market sizing data, key players analysis, regulatory landscape across major markets, and technological innovation timelines..." }, { "role": "Analysis-Agent", "content": "Statistical analysis of renewable energy adoption patterns showing compound growth rates, learning curve analysis for solar PV and wind technologies, correlation between policy incentives and deployment rates..." }, { "role": "Alternatives-Agent", "content": "Strategic investment alternatives analysis covering direct equity positions, ETF-based approaches, project finance opportunities, and emerging technology bets with detailed risk-return profiles..." }, { "role": "Verification-Agent", "content": "Verification assessment of key claims including cross-referenced deployment data, validated cost projections against IRENA and BloombergNEF databases, feasibility assessment of grid integration targets..." }, { "role": "Synthesis-Agent", "content": "Executive Summary: The renewable energy sector presents strong investment fundamentals with verified compound growth trajectories. Key Insights: Solar PV costs have declined 89% since 2010, wind energy capacity factors have improved 25%... Actionable Recommendations: 1. Overweight solar and battery storage... Risks & Mitigation: Supply chain concentration in key materials..." } ], "number_of_agents": 5, "execution_time": 62.4, "usage": { "input_tokens": 85, "output_tokens": 5400, "total_tokens": 5485, "billing_info": { "cost_breakdown": { "agent_cost": 0.05, "input_token_cost": 0.000553, "output_token_cost": 0.0999, "token_counts": { "total_input_tokens": 85, "total_output_tokens": 5400, "total_tokens": 5485 }, "num_agents": 5, "night_time_discount_applied": false }, "total_cost": 0.150452, "discount_active": false, "discount_type": "none", "discount_percentage": 0 } } } ``` ## Best Practices * Use HeavySwarm for complex tasks that benefit from multi-perspective analysis rather than simple queries * Start with `heavy_swarm_max_loops: 1` and increase only when deeper iterative analysis is needed * Choose the question agent model carefully — it determines the quality of task decomposition which drives the entire workflow * Use a capable worker model (e.g., `claude-sonnet-4-20250514`) for the specialized agents to get high-quality research, analysis, and verification * HeavySwarm requires an empty `agents` array (`"agents": []`) in the request — all five agents are created and managed internally * For time-sensitive tasks, keep `max_loops` at 1; increase for comprehensive research where thoroughness is prioritized over speed * Schedule non-urgent deep analysis during off-peak hours (8 PM - 6 AM PT) for cost savings # HierarchicalSwarm Source: https://docs.swarms.ai/docs/documentation/multi-agent/hierarchical_swarm Multi-level swarm architecture with supervisor agents coordinating specialized worker agents in a hierarchical structure **Swarm Type**: `HierarchicalSwarm` ## Overview The HierarchicalSwarm implements a multi-level organizational structure where supervisor agents coordinate and manage specialized worker agents. This architecture mirrors real-world organizational hierarchies, allowing for complex task decomposition, quality control, and efficient resource allocation across multiple levels of responsibility. Key features: * **Multi-Level Structure**: Supervisor and worker agent hierarchy * **Task Decomposition**: Complex tasks broken down into manageable subtasks * **Quality Control**: Supervisors oversee and validate worker outputs * **Resource Coordination**: Efficient allocation and management of agent resources ## Architecture ```mermaid theme={null} flowchart TD T["Task"] --> S["Supervisor"] S --> W1["Worker 1"] S --> W2["Worker 2"] S --> W3["Worker 3"] W1 --> V["Supervisor reviews and synthesizes"] W2 --> V W3 --> V V --> O["Result"] ``` The supervisor splits the task, hands pieces to workers, then validates and merges what comes back. ## Use Cases * Complex project management and coordination * Multi-stage research and analysis workflows * Content creation with editorial oversight * Quality assurance and validation processes ## API Usage ### Basic HierarchicalSwarm Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Project Coordinator", "description": "Hierarchical research coordination with supervisor oversight", "swarm_type": "HierarchicalSwarm", "task": "Conduct comprehensive research on the impact of AI on healthcare, including technological advances, economic implications, ethical considerations, and future trends", "agents": [ { "agent_name": "Research Coordinator", "description": "Supervisor agent coordinating research efforts and synthesizing results", "system_prompt": "You are a research coordinator supervising a team of specialized researchers. Delegate tasks, coordinate efforts, and synthesize final results into a comprehensive report.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technology Researcher", "description": "Worker agent researching AI technological advances in healthcare", "system_prompt": "You are a technology researcher specializing in AI healthcare applications. Research and analyze current technological advances, breakthroughs, and implementation challenges.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Worker agent analyzing economic implications of AI in healthcare", "system_prompt": "You are an economic analyst specializing in healthcare economics. Research and analyze the economic implications, cost-benefit analysis, and market impact of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Ethics Specialist", "description": "Worker agent examining ethical considerations of AI in healthcare", "system_prompt": "You are an ethics specialist focusing on AI and healthcare ethics. Research and analyze ethical considerations, privacy concerns, bias issues, and regulatory implications.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Future Trends Analyst", "description": "Worker agent predicting future trends in AI healthcare", "system_prompt": "You are a future trends analyst specializing in healthcare technology. Research and analyze future trends, predictions, and long-term implications of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Research Project Coordinator", "description": "Hierarchical research coordination with supervisor oversight", "swarm_type": "HierarchicalSwarm", "task": "Conduct comprehensive research on the impact of AI on healthcare, including technological advances, economic implications, ethical considerations, and future trends", "agents": [ { "agent_name": "Research Coordinator", "description": "Supervisor agent coordinating research efforts and synthesizing results", "system_prompt": "You are a research coordinator supervising a team of specialized researchers. Delegate tasks, coordinate efforts, and synthesize final results into a comprehensive report.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technology Researcher", "description": "Worker agent researching AI technological advances in healthcare", "system_prompt": "You are a technology researcher specializing in AI healthcare applications. Research and analyze current technological advances, breakthroughs, and implementation challenges.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Worker agent analyzing economic implications of AI in healthcare", "system_prompt": "You are an economic analyst specializing in healthcare economics. Research and analyze the economic implications, cost-benefit analysis, and market impact of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Ethics Specialist", "description": "Worker agent examining ethical considerations of AI in healthcare", "system_prompt": "You are an ethics specialist focusing on AI and healthcare ethics. Research and analyze ethical considerations, privacy concerns, bias issues, and regulatory implications.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Future Trends Analyst", "description": "Worker agent predicting future trends in AI healthcare", "system_prompt": "You are a future trends analyst specializing in healthcare technology. Research and analyze future trends, predictions, and long-term implications of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("HierarchicalSwarm swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Hierarchical results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Research Project Coordinator", description: "Hierarchical research coordination with supervisor oversight", swarm_type: "HierarchicalSwarm", task: "Conduct comprehensive research on the impact of AI on healthcare, including technological advances, economic implications, ethical considerations, and future trends", agents: [ { agent_name: "Research Coordinator", description: "Supervisor agent coordinating research efforts and synthesizing results", system_prompt: "You are a research coordinator supervising a team of specialized researchers. Delegate tasks, coordinate efforts, and synthesize final results into a comprehensive report.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Technology Researcher", description: "Worker agent researching AI technological advances in healthcare", system_prompt: "You are a technology researcher specializing in AI healthcare applications. Research and analyze current technological advances, breakthroughs, and implementation challenges.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Economic Analyst", description: "Worker agent analyzing economic implications of AI in healthcare", system_prompt: "You are an economic analyst specializing in healthcare economics. Research and analyze the economic implications, cost-benefit analysis, and market impact of AI in healthcare.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Ethics Specialist", description: "Worker agent examining ethical considerations of AI in healthcare", system_prompt: "You are an ethics specialist focusing on AI and healthcare ethics. Research and analyze ethical considerations, privacy concerns, bias issues, and regulatory implications.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Future Trends Analyst", description: "Worker agent predicting future trends in AI healthcare", system_prompt: "You are a future trends analyst specializing in healthcare technology. Research and analyze future trends, predictions, and long-term implications of AI in healthcare.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("HierarchicalSwarm swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Hierarchical results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Research Project Coordinator", Description: "Hierarchical research coordination with supervisor oversight", SwarmType: "HierarchicalSwarm", Task: "Conduct comprehensive research on the impact of AI on healthcare, including technological advances, economic implications, ethical considerations, and future trends", Agents: []Agent{ { AgentName: "Research Coordinator", Description: "Supervisor agent coordinating research efforts and synthesizing results", SystemPrompt: "You are a research coordinator supervising a team of specialized researchers. Delegate tasks, coordinate efforts, and synthesize final results into a comprehensive report.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Technology Researcher", Description: "Worker agent researching AI technological advances in healthcare", SystemPrompt: "You are a technology researcher specializing in AI healthcare applications. Research and analyze current technological advances, breakthroughs, and implementation challenges.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Economic Analyst", Description: "Worker agent analyzing economic implications of AI in healthcare", SystemPrompt: "You are an economic analyst specializing in healthcare economics. Research and analyze the economic implications, cost-benefit analysis, and market impact of AI in healthcare.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Ethics Specialist", Description: "Worker agent examining ethical considerations of AI in healthcare", SystemPrompt: "You are an ethics specialist focusing on AI and healthcare ethics. Research and analyze ethical considerations, privacy concerns, bias issues, and regulatory implications.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Future Trends Analyst", Description: "Worker agent predicting future trends in AI healthcare", SystemPrompt: "You are a future trends analyst specializing in healthcare technology. Research and analyze future trends, predictions, and long-term implications of AI in healthcare.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Research Project Coordinator", "description": "Hierarchical research coordination with supervisor oversight", "swarm_type": "HierarchicalSwarm", "task": "Conduct comprehensive research on the impact of AI on healthcare, including technological advances, economic implications, ethical considerations, and future trends", "agents": [ { "agent_name": "Research Coordinator", "description": "Supervisor agent coordinating research efforts and synthesizing results", "system_prompt": "You are a research coordinator supervising a team of specialized researchers. Delegate tasks, coordinate efforts, and synthesize final results into a comprehensive report.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technology Researcher", "description": "Worker agent researching AI technological advances in healthcare", "system_prompt": "You are a technology researcher specializing in AI healthcare applications. Research and analyze current technological advances, breakthroughs, and implementation challenges.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Worker agent analyzing economic implications of AI in healthcare", "system_prompt": "You are an economic analyst specializing in healthcare economics. Research and analyze the economic implications, cost-benefit analysis, and market impact of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Ethics Specialist", "description": "Worker agent examining ethical considerations of AI in healthcare", "system_prompt": "You are an ethics specialist focusing on AI and healthcare ethics. Research and analyze ethical considerations, privacy concerns, bias issues, and regulatory implications.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Future Trends Analyst", "description": "Worker agent predicting future trends in AI healthcare", "system_prompt": "You are a future trends analyst specializing in healthcare technology. Research and analyze future trends, predictions, and long-term implications of AI in healthcare.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("HierarchicalSwarm swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-H17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Research Project Coordinator", "description": "Hierarchical research coordination with supervisor oversight", "swarm_type": "HierarchicalSwarm", "output": [ { "role": "Research Coordinator", "content": "As the Research Coordinator, I have synthesized the findings from our specialized research team into a comprehensive report on AI's impact on healthcare..." }, { "role": "Technology Researcher", "content": "My research on AI technological advances in healthcare reveals significant breakthroughs in diagnostic imaging, drug discovery, and personalized medicine..." }, { "role": "Economic Analyst", "content": "The economic analysis shows that AI in healthcare could reduce costs by 15-20% while improving outcomes, though initial implementation costs are substantial..." }, { "role": "Ethics Specialist", "content": "Ethical considerations include data privacy, algorithmic bias, transparency in decision-making, and ensuring human oversight in critical healthcare decisions..." }, { "role": "Future Trends Analyst", "content": "Future trends indicate rapid adoption of AI in preventive care, remote monitoring, and personalized treatment plans, with full integration expected within 5-10 years..." } ], "number_of_agents": 5, "execution_time": 45.8, "usage": { "input_tokens": 55, "output_tokens": 3200, "total_tokens": 3255, "billing_info": { "cost_breakdown": { "agent_cost": 0.05, "input_token_cost": 0.000179, "output_token_cost": 0.0296, "token_counts": { "total_input_tokens": 55, "total_output_tokens": 3200, "total_tokens": 3255 }, "num_agents": 5, "night_time_discount_applied": true }, "total_cost": 0.079779, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Configuring the Director `HierarchicalSwarm` runs a director agent that decomposes the task and delegates it to your worker agents. The director is created by the swarm itself rather than supplied in the `agents` array, so it is configured through two top-level `SwarmSpec` fields. | Parameter | Type | Default | Description | | --------------------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------- | | `director_model_name` | `string` | `"gpt-5.4"` | The model the director uses to plan and delegate. | | `director_settings` | `object` | `{}` | Sampling and generation settings for the director, such as `temperature`, `top_p`, and `max_tokens`. | ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Project Coordinator", "swarm_type": "HierarchicalSwarm", "task": "Research the impact of AI on healthcare", "director_model_name": "gpt-5.4", "director_settings": { "temperature": 0.2, "max_tokens": 4000 }, "agents": [ { "agent_name": "Technology Researcher", "system_prompt": "You research AI technology in healthcare.", "model_name": "gpt-4.1" } ] }' ``` ```python theme={null} import os import requests response = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.getenv("SWARMS_API_KEY")}, json={ "name": "Research Project Coordinator", "swarm_type": "HierarchicalSwarm", "task": "Research the impact of AI on healthcare", "director_model_name": "gpt-5.4", "director_settings": { "temperature": 0.2, "max_tokens": 4000, }, "agents": [ { "agent_name": "Technology Researcher", "system_prompt": "You research AI technology in healthcare.", "model_name": "gpt-4.1", } ], }, ) print(response.json()) ``` A lower `temperature` on the director produces more consistent task decomposition and delegation, while worker agents can keep a higher temperature for creative output. ## Best Practices * Design clear supervisor-worker relationships * Ensure supervisors can effectively coordinate and synthesize results * Use a capable `director_model_name` — the director's plan determines how well the workers perform * Lower the director's `temperature` for more deterministic task decomposition * Use for complex projects requiring oversight and coordination * Ideal for research, content creation, and project management # MajorityVoting Source: https://docs.swarms.ai/docs/documentation/multi-agent/majority_voting Democratic decision-making swarm where multiple agents vote on solutions, with the majority determining the final outcome **Swarm Type**: `MajorityVoting` ## Overview The MajorityVoting swarm type implements a democratic decision-making process where multiple agents independently analyze a problem and propose solutions. The final outcome is determined by majority consensus, making this architecture ideal for scenarios where you want to leverage collective intelligence while maintaining a clear decision-making process. Key features: * **Democratic Decision Making**: Multiple agents vote on solutions * **Consensus Building**: Majority rule determines final outcome * **Independent Analysis**: Each agent works independently before voting * **Transparent Process**: Clear voting mechanism and results ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A["Agent 1 votes"] T --> B["Agent 2 votes"] T --> C["Agent 3 votes"] A --> V["Majority consensus"] B --> V C --> V V --> O["Final outcome"] ``` Each agent decides independently, without seeing the others. The majority answer wins. ## Use Cases * Content quality assessment and approval * Problem diagnosis with multiple expert opinions * Decision-making in uncertain scenarios * Quality control and validation processes ## API Usage ### Basic MajorityVoting Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Content Quality Assessment", "description": "Multi-agent content review with majority voting for approval", "swarm_type": "MajorityVoting", "task": "Review and vote on whether to approve this marketing content for publication: [Content: Our revolutionary AI solution transforms business operations by leveraging cutting-edge machine learning algorithms to optimize workflows and increase productivity by up to 300%]", "agents": [ { "agent_name": "Marketing Expert", "description": "Evaluates marketing effectiveness and messaging", "system_prompt": "You are a marketing expert. Assess marketing content for effectiveness, clarity, and appeal to target audiences. Vote YES if the content is ready for publication, NO if it needs revision.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Reviewer", "description": "Reviews technical accuracy and claims", "system_prompt": "You are a technical reviewer. Assess the technical accuracy of claims and ensure they are substantiated. Vote YES if claims are accurate, NO if they are exaggerated or unsubstantiated.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Legal Compliance", "description": "Checks for legal and compliance issues", "system_prompt": "You are a legal compliance expert. Review content for potential legal issues, compliance concerns, and regulatory requirements. Vote YES if content is compliant, NO if there are legal concerns.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 }, { "agent_name": "Brand Guardian", "description": "Ensures brand consistency and voice", "system_prompt": "You are a brand guardian. Ensure content aligns with brand voice, values, and positioning. Vote YES if content fits the brand, NO if it needs brand alignment adjustments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Audience Advocate", "description": "Represents the target audience perspective", "system_prompt": "You are an audience advocate. Evaluate whether the content is clear, credible, and persuasive from the perspective of the target audience. Vote YES if the content would resonate with readers, NO if it would not.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Content Quality Assessment", "description": "Multi-agent content review with majority voting for approval", "swarm_type": "MajorityVoting", "task": "Review and vote on whether to approve this marketing content for publication: [Content: Our revolutionary AI solution transforms business operations by leveraging cutting-edge machine learning algorithms to optimize workflows and increase productivity by up to 300%]", "agents": [ { "agent_name": "Marketing Expert", "description": "Evaluates marketing effectiveness and messaging", "system_prompt": "You are a marketing expert. Assess marketing content for effectiveness, clarity, and appeal to target audiences. Vote YES if the content is ready for publication, NO if it needs revision.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Reviewer", "description": "Reviews technical accuracy and claims", "system_prompt": "You are a technical reviewer. Assess the technical accuracy of claims and ensure they are substantiated. Vote YES if claims are accurate, NO if they are exaggerated or unsubstantiated.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Legal Compliance", "description": "Checks for legal and compliance issues", "system_prompt": "You are a legal compliance expert. Review content for potential legal issues, compliance concerns, and regulatory requirements. Vote YES if content is compliant, NO if there are legal concerns.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 }, { "agent_name": "Brand Guardian", "description": "Ensures brand consistency and voice", "system_prompt": "You are a brand guardian. Ensure content aligns with brand voice, values, and positioning. Vote YES if content fits the brand, NO if it needs brand alignment adjustments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Audience Advocate", "description": "Represents the target audience perspective", "system_prompt": "You are an audience advocate. Evaluate whether the content is clear, credible, and persuasive from the perspective of the target audience. Vote YES if the content would resonate with readers, NO if it would not.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("MajorityVoting swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Voting results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Content Quality Assessment", description: "Multi-agent content review with majority voting for approval", swarm_type: "MajorityVoting", task: "Review and vote on whether to approve this marketing content for publication: [Content: Our revolutionary AI solution transforms business operations by leveraging cutting-edge machine learning algorithms to optimize workflows and increase productivity by up to 300%]", agents: [ { agent_name: "Marketing Expert", description: "Evaluates marketing effectiveness and messaging", system_prompt: "You are a marketing expert. Assess marketing content for effectiveness, clarity, and appeal to target audiences. Vote YES if the content is ready for publication, NO if it needs revision.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Technical Reviewer", description: "Reviews technical accuracy and claims", system_prompt: "You are a technical reviewer. Assess the technical accuracy of claims and ensure they are substantiated. Vote YES if claims are accurate, NO if they are exaggerated or unsubstantiated.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.2 }, { agent_name: "Legal Compliance", description: "Checks for legal and compliance issues", system_prompt: "You are a legal compliance expert. Review content for potential legal issues, compliance concerns, and regulatory requirements. Vote YES if content is compliant, NO if there are legal concerns.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.1 }, { agent_name: "Brand Guardian", description: "Ensures brand consistency and voice", system_prompt: "You are a brand guardian. Ensure content aligns with brand voice, values, and positioning. Vote YES if content fits the brand, NO if it needs brand alignment adjustments.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 }, { agent_name: "Audience Advocate", description: "Represents the target audience perspective", system_prompt: "You are an audience advocate. Evaluate whether the content is clear, credible, and persuasive from the perspective of the target audience. Vote YES if the content would resonate with readers, NO if it would not.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("MajorityVoting swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Voting results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Content Quality Assessment", Description: "Multi-agent content review with majority voting for approval", SwarmType: "MajorityVoting", Task: "Review and vote on whether to approve this marketing content for publication: [Content: Our revolutionary AI solution transforms business operations by leveraging cutting-edge machine learning algorithms to optimize workflows and increase productivity by up to 300%]", Agents: []Agent{ { AgentName: "Marketing Expert", Description: "Evaluates marketing effectiveness and messaging", SystemPrompt: "You are a marketing expert. Assess marketing content for effectiveness, clarity, and appeal to target audiences. Vote YES if the content is ready for publication, NO if it needs revision.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Technical Reviewer", Description: "Reviews technical accuracy and claims", SystemPrompt: "You are a technical reviewer. Assess the technical accuracy of claims and ensure they are substantiated. Vote YES if claims are accurate, NO if they are exaggerated or unsubstantiated.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.2, }, { AgentName: "Legal Compliance", Description: "Checks for legal and compliance issues", SystemPrompt: "You are a legal compliance expert. Review content for potential legal issues, compliance concerns, and regulatory requirements. Vote YES if content is compliant, NO if there are legal concerns.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.1, }, { AgentName: "Brand Guardian", Description: "Ensures brand consistency and voice", SystemPrompt: "You are a brand guardian. Ensure content aligns with brand voice, values, and positioning. Vote YES if content fits the brand, NO if it needs brand alignment adjustments.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, { AgentName: "Audience Advocate", Description: "Represents the target audience perspective", SystemPrompt: "You are an audience advocate. Evaluate whether the content is clear, credible, and persuasive from the perspective of the target audience. Vote YES if the content would resonate with readers, NO if it would not.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Content Quality Assessment", "description": "Multi-agent content review with majority voting for approval", "swarm_type": "MajorityVoting", "task": "Review and vote on whether to approve this marketing content for publication: [Content: Our revolutionary AI solution transforms business operations by leveraging cutting-edge machine learning algorithms to optimize workflows and increase productivity by up to 300%]", "agents": [ { "agent_name": "Marketing Expert", "description": "Evaluates marketing effectiveness and messaging", "system_prompt": "You are a marketing expert. Assess marketing content for effectiveness, clarity, and appeal to target audiences. Vote YES if the content is ready for publication, NO if it needs revision.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Reviewer", "description": "Reviews technical accuracy and claims", "system_prompt": "You are a technical reviewer. Assess the technical accuracy of claims and ensure they are substantiated. Vote YES if claims are accurate, NO if they are exaggerated or unsubstantiated.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Legal Compliance", "description": "Checks for legal and compliance issues", "system_prompt": "You are a legal compliance expert. Review content for potential legal issues, compliance concerns, and regulatory requirements. Vote YES if content is compliant, NO if there are legal concerns.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 }, { "agent_name": "Brand Guardian", "description": "Ensures brand consistency and voice", "system_prompt": "You are a brand guardian. Ensure content aligns with brand voice, values, and positioning. Vote YES if content fits the brand, NO if it needs brand alignment adjustments.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Audience Advocate", "description": "Represents the target audience perspective", "system_prompt": "You are an audience advocate. Evaluate whether the content is clear, credible, and persuasive from the perspective of the target audience. Vote YES if the content would resonate with readers, NO if it would not.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("MajorityVoting swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-V17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Content Quality Assessment", "description": "Multi-agent content review with majority voting for approval", "swarm_type": "MajorityVoting", "output": [ { "role": "Marketing Expert", "content": "VOTE: YES. The content effectively communicates the value proposition and uses compelling language that would resonate with business audiences." }, { "role": "Technical Reviewer", "content": "VOTE: NO. The claim of '300% productivity increase' is not substantiated and could be considered misleading without specific data." }, { "role": "Legal Compliance", "content": "VOTE: NO. The unsubstantiated productivity claim could potentially violate advertising standards and truth-in-advertising regulations." }, { "role": "Brand Guardian", "content": "VOTE: YES. The content aligns well with our brand voice of innovation and transformation." }, { "role": "Audience Advocate", "content": "VOTE: NO. The '300% productivity increase' claim reads as implausible and undermines the credibility of the message for a business audience." } ], "number_of_agents": 5, "execution_time": 28.7, "usage": { "input_tokens": 50, "output_tokens": 1800, "total_tokens": 1850, "billing_info": { "cost_breakdown": { "agent_cost": 0.05, "input_token_cost": 0.000163, "output_token_cost": 0.01665, "token_counts": { "total_input_tokens": 50, "total_output_tokens": 1800, "total_tokens": 1850 }, "num_agents": 5, "night_time_discount_applied": true }, "total_cost": 0.066812, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Use an odd number of agents to avoid tie votes * Design agents with distinct evaluation criteria * Ensure clear voting instructions in system prompts * Ideal for quality control and approval workflows # MixtureOfAgents Source: https://docs.swarms.ai/docs/documentation/multi-agent/mixture_of_agents Collaborative swarm where multiple agents work together on the same task, combining their expertise for comprehensive solutions **Swarm Type**: `MixtureOfAgents` ## Overview The MixtureOfAgents swarm type brings together multiple specialized agents to work collaboratively on the same task. This architecture leverages the collective intelligence and diverse perspectives of multiple agents, combining their expertise to produce more comprehensive and nuanced solutions than any single agent could achieve alone. Key features: * **Collaborative Analysis**: Multiple agents work together on the same task * **Diverse Perspectives**: Different viewpoints and expertise areas * **Comprehensive Solutions**: Combined insights from multiple specialists * **Enhanced Quality**: Better results through collective intelligence ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A["Specialist A"] T --> B["Specialist B"] T --> C["Specialist C"] A --> S["Combined solution"] B --> S C --> S ``` Every specialist sees the same task, and their perspectives are combined into one answer. ## Use Cases * Complex problem analysis requiring multiple viewpoints * Content creation with multiple expert perspectives * Research projects needing interdisciplinary approaches * Decision-making with diverse stakeholder input ## API Usage ### Basic MixtureOfAgents Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Comprehensive Market Analysis", "description": "Multi-perspective market analysis combining various expert viewpoints", "swarm_type": "MixtureOfAgents", "task": "Analyze the current state and future prospects of the electric vehicle market from multiple perspectives", "agents": [ { "agent_name": "Technology Analyst", "description": "Analyzes technological trends and innovations", "system_prompt": "You are a technology analyst specializing in automotive and battery technologies. Focus on technological advancements, innovation trends, and technical challenges in the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Analyzes market economics and financial aspects", "system_prompt": "You are an economic analyst specializing in automotive markets. Focus on market economics, pricing trends, cost analysis, and financial viability of EV adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Environmental Specialist", "description": "Analyzes environmental impact and sustainability", "system_prompt": "You are an environmental specialist focusing on sustainability. Analyze the environmental impact of EVs, lifecycle analysis, and sustainability benefits compared to traditional vehicles.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Policy Expert", "description": "Analyzes regulatory and policy landscape", "system_prompt": "You are a policy expert specializing in automotive regulations. Focus on government policies, incentives, regulatory requirements, and policy trends affecting the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Comprehensive Market Analysis", "description": "Multi-perspective market analysis combining various expert viewpoints", "swarm_type": "MixtureOfAgents", "task": "Analyze the current state and future prospects of the electric vehicle market from multiple perspectives", "agents": [ { "agent_name": "Technology Analyst", "description": "Analyzes technological trends and innovations", "system_prompt": "You are a technology analyst specializing in automotive and battery technologies. Focus on technological advancements, innovation trends, and technical challenges in the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Analyzes market economics and financial aspects", "system_prompt": "You are an economic analyst specializing in automotive markets. Focus on market economics, pricing trends, cost analysis, and financial viability of EV adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Environmental Specialist", "description": "Analyzes environmental impact and sustainability", "system_prompt": "You are an environmental specialist focusing on sustainability. Analyze the environmental impact of EVs, lifecycle analysis, and sustainability benefits compared to traditional vehicles.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Policy Expert", "description": "Analyzes regulatory and policy landscape", "system_prompt": "You are a policy expert specializing in automotive regulations. Focus on government policies, incentives, regulatory requirements, and policy trends affecting the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("MixtureOfAgents swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Collaborative results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Comprehensive Market Analysis", description: "Multi-perspective market analysis combining various expert viewpoints", swarm_type: "MixtureOfAgents", task: "Analyze the current state and future prospects of the electric vehicle market from multiple perspectives", agents: [ { agent_name: "Technology Analyst", description: "Analyzes technological trends and innovations", system_prompt: "You are a technology analyst specializing in automotive and battery technologies. Focus on technological advancements, innovation trends, and technical challenges in the EV market.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Economic Analyst", description: "Analyzes market economics and financial aspects", system_prompt: "You are an economic analyst specializing in automotive markets. Focus on market economics, pricing trends, cost analysis, and financial viability of EV adoption.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Environmental Specialist", description: "Analyzes environmental impact and sustainability", system_prompt: "You are an environmental specialist focusing on sustainability. Analyze the environmental impact of EVs, lifecycle analysis, and sustainability benefits compared to traditional vehicles.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Policy Expert", description: "Analyzes regulatory and policy landscape", system_prompt: "You are a policy expert specializing in automotive regulations. Focus on government policies, incentives, regulatory requirements, and policy trends affecting the EV market.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("MixtureOfAgents swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Collaborative results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Comprehensive Market Analysis", Description: "Multi-perspective market analysis combining various expert viewpoints", SwarmType: "MixtureOfAgents", Task: "Analyze the current state and future prospects of the electric vehicle market from multiple perspectives", Agents: []Agent{ { AgentName: "Technology Analyst", Description: "Analyzes technological trends and innovations", SystemPrompt: "You are a technology analyst specializing in automotive and battery technologies. Focus on technological advancements, innovation trends, and technical challenges in the EV market.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Economic Analyst", Description: "Analyzes market economics and financial aspects", SystemPrompt: "You are an economic analyst specializing in automotive markets. Focus on market economics, pricing trends, cost analysis, and financial viability of EV adoption.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Environmental Specialist", Description: "Analyzes environmental impact and sustainability", SystemPrompt: "You are an environmental specialist focusing on sustainability. Analyze the environmental impact of EVs, lifecycle analysis, and sustainability benefits compared to traditional vehicles.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Policy Expert", Description: "Analyzes regulatory and policy landscape", SystemPrompt: "You are a policy expert specializing in automotive regulations. Focus on government policies, incentives, regulatory requirements, and policy trends affecting the EV market.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Comprehensive Market Analysis", "description": "Multi-perspective market analysis combining various expert viewpoints", "swarm_type": "MixtureOfAgents", "task": "Analyze the current state and future prospects of the electric vehicle market from multiple perspectives", "agents": [ { "agent_name": "Technology Analyst", "description": "Analyzes technological trends and innovations", "system_prompt": "You are a technology analyst specializing in automotive and battery technologies. Focus on technological advancements, innovation trends, and technical challenges in the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Economic Analyst", "description": "Analyzes market economics and financial aspects", "system_prompt": "You are an economic analyst specializing in automotive markets. Focus on market economics, pricing trends, cost analysis, and financial viability of EV adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Environmental Specialist", "description": "Analyzes environmental impact and sustainability", "system_prompt": "You are an environmental specialist focusing on sustainability. Analyze the environmental impact of EVs, lifecycle analysis, and sustainability benefits compared to traditional vehicles.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Policy Expert", "description": "Analyzes regulatory and policy landscape", "system_prompt": "You are a policy expert specializing in automotive regulations. Focus on government policies, incentives, regulatory requirements, and policy trends affecting the EV market.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("MixtureOfAgents swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-M17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Comprehensive Market Analysis", "description": "Multi-perspective market analysis combining various expert viewpoints", "swarm_type": "MixtureOfAgents", "output": [ { "role": "Technology Analyst", "content": "From a technological perspective, the EV market is experiencing rapid innovation in battery technology, with solid-state batteries and improved energy density..." }, { "role": "Economic Analyst", "content": "Economically, the EV market shows strong growth potential with declining battery costs and increasing consumer adoption..." }, { "role": "Environmental Specialist", "content": "Environmentally, EVs offer significant benefits in reducing greenhouse gas emissions, though the full lifecycle impact depends on electricity sources..." }, { "role": "Policy Expert", "content": "Policy-wise, governments worldwide are implementing various incentives and regulations to accelerate EV adoption..." } ], "number_of_agents": 4, "execution_time": 32.1, "usage": { "input_tokens": 40, "output_tokens": 2800, "total_tokens": 2840, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.00013, "output_token_cost": 0.0259, "token_counts": { "total_input_tokens": 40, "total_output_tokens": 2800, "total_tokens": 2840 }, "num_agents": 4, "night_time_discount_applied": true }, "total_cost": 0.06603, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Design agents with complementary but distinct expertise areas * Use for complex tasks requiring multiple perspectives * Ensure agents can work collaboratively on the same problem * Ideal for comprehensive analysis and decision-making # MultiAgentRouter Source: https://docs.swarms.ai/docs/documentation/multi-agent/multi_agent_router Intelligent task dispatcher that distributes work based on agent capabilities and workload optimization **Swarm Type**: `MultiAgentRouter` ## Overview The MultiAgentRouter acts as an intelligent task dispatcher, distributing work across agents based on their capabilities and current workload. This architecture analyzes incoming tasks and automatically routes them to the most suitable agents, optimizing both efficiency and quality of outcomes. Key features: * **Intelligent Routing**: Automatically assigns tasks to best-suited agents * **Capability Matching**: Matches task requirements with agent specializations * **Load Balancing**: Distributes workload efficiently across available agents * **Dynamic Assignment**: Adapts routing based on agent performance and availability ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> R{"Router"} R -->|"best match"| A["Billing Agent"] R -.-> B["Technical Agent"] R -.-> C["Sales Agent"] A --> O["Result"] ``` The router reads the task and dispatches it to the best-suited agent. Agents it does not pick, shown dashed, never run. ## Use Cases * Customer service request routing * Content categorization and processing * Technical support ticket assignment * Multi-domain question answering ## API Usage ### Basic MultiAgentRouter Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Customer Support Router", "description": "Route customer inquiries to specialized support agents", "swarm_type": "MultiAgentRouter", "task": "Handle multiple customer inquiries: 1) Billing question about overcharge, 2) Technical issue with mobile app login, 3) Product recommendation for enterprise client, 4) Return policy question", "agents": [ { "agent_name": "Billing Specialist", "description": "Handles billing, payments, and account issues", "system_prompt": "You are a billing specialist. Handle all billing inquiries, payment issues, refunds, and account-related questions with empathy and accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Support", "description": "Resolves technical issues and troubleshooting", "system_prompt": "You are a technical support specialist. Diagnose and resolve technical issues, provide step-by-step troubleshooting, and escalate complex problems.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Sales Consultant", "description": "Provides product recommendations and sales support", "system_prompt": "You are a sales consultant. Provide product recommendations, explain features and benefits, and help customers find the right solutions.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Policy Advisor", "description": "Explains company policies and procedures", "system_prompt": "You are a policy advisor. Explain company policies, terms of service, return procedures, and compliance requirements clearly.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Customer Support Router", "description": "Route customer inquiries to specialized support agents", "swarm_type": "MultiAgentRouter", "task": "Handle multiple customer inquiries: 1) Billing question about overcharge, 2) Technical issue with mobile app login, 3) Product recommendation for enterprise client, 4) Return policy question", "agents": [ { "agent_name": "Billing Specialist", "description": "Handles billing, payments, and account issues", "system_prompt": "You are a billing specialist. Handle all billing inquiries, payment issues, refunds, and account-related questions with empathy and accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Support", "description": "Resolves technical issues and troubleshooting", "system_prompt": "You are a technical support specialist. Diagnose and resolve technical issues, provide step-by-step troubleshooting, and escalate complex problems.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Sales Consultant", "description": "Provides product recommendations and sales support", "system_prompt": "You are a sales consultant. Provide product recommendations, explain features and benefits, and help customers find the right solutions.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Policy Advisor", "description": "Explains company policies and procedures", "system_prompt": "You are a policy advisor. Explain company policies, terms of service, return procedures, and compliance requirements clearly.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("MultiAgentRouter swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Routed results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Customer Support Router", description: "Route customer inquiries to specialized support agents", swarm_type: "MultiAgentRouter", task: "Handle multiple customer inquiries: 1) Billing question about overcharge, 2) Technical issue with mobile app login, 3) Product recommendation for enterprise client, 4) Return policy question", agents: [ { agent_name: "Billing Specialist", description: "Handles billing, payments, and account issues", system_prompt: "You are a billing specialist. Handle all billing inquiries, payment issues, refunds, and account-related questions with empathy and accuracy.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Technical Support", description: "Resolves technical issues and troubleshooting", system_prompt: "You are a technical support specialist. Diagnose and resolve technical issues, provide step-by-step troubleshooting, and escalate complex problems.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.2 }, { agent_name: "Sales Consultant", description: "Provides product recommendations and sales support", system_prompt: "You are a sales consultant. Provide product recommendations, explain features and benefits, and help customers find the right solutions.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 }, { agent_name: "Policy Advisor", description: "Explains company policies and procedures", system_prompt: "You are a policy advisor. Explain company policies, terms of service, return procedures, and compliance requirements clearly.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.1 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("MultiAgentRouter swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Routed results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Customer Support Router", Description: "Route customer inquiries to specialized support agents", SwarmType: "MultiAgentRouter", Task: "Handle multiple customer inquiries: 1) Billing question about overcharge, 2) Technical issue with mobile app login, 3) Product recommendation for enterprise client, 4) Return policy question", Agents: []Agent{ { AgentName: "Billing Specialist", Description: "Handles billing, payments, and account issues", SystemPrompt: "You are a billing specialist. Handle all billing inquiries, payment issues, refunds, and account-related questions with empathy and accuracy.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Technical Support", Description: "Resolves technical issues and troubleshooting", SystemPrompt: "You are a technical support specialist. Diagnose and resolve technical issues, provide step-by-step troubleshooting, and escalate complex problems.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.2, }, { AgentName: "Sales Consultant", Description: "Provides product recommendations and sales support", SystemPrompt: "You are a sales consultant. Provide product recommendations, explain features and benefits, and help customers find the right solutions.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, { AgentName: "Policy Advisor", Description: "Explains company policies and procedures", SystemPrompt: "You are a policy advisor. Explain company policies, terms of service, return procedures, and compliance requirements clearly.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.1, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Customer Support Router", "description": "Route customer inquiries to specialized support agents", "swarm_type": "MultiAgentRouter", "task": "Handle multiple customer inquiries: 1) Billing question about overcharge, 2) Technical issue with mobile app login, 3) Product recommendation for enterprise client, 4) Return policy question", "agents": [ { "agent_name": "Billing Specialist", "description": "Handles billing, payments, and account issues", "system_prompt": "You are a billing specialist. Handle all billing inquiries, payment issues, refunds, and account-related questions with empathy and accuracy.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Technical Support", "description": "Resolves technical issues and troubleshooting", "system_prompt": "You are a technical support specialist. Diagnose and resolve technical issues, provide step-by-step troubleshooting, and escalate complex problems.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Sales Consultant", "description": "Provides product recommendations and sales support", "system_prompt": "You are a sales consultant. Provide product recommendations, explain features and benefits, and help customers find the right solutions.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Policy Advisor", "description": "Explains company policies and procedures", "system_prompt": "You are a policy advisor. Explain company policies, terms of service, return procedures, and compliance requirements clearly.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("MultiAgentRouter swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-R17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Customer Support Router", "description": "Route customer inquiries to specialized support agents", "swarm_type": "MultiAgentRouter", "output": [ { "role": "Billing Specialist", "content": "I'll handle the billing question about the overcharge. Let me review your account and explain the charges..." }, { "role": "Technical Support", "content": "I'll help you resolve the mobile app login issue. Let's troubleshoot this step by step..." }, { "role": "Sales Consultant", "content": "I'll provide product recommendations for your enterprise client. Based on their needs..." }, { "role": "Policy Advisor", "content": "I'll explain our return policy clearly. Here are the key points you need to know..." } ], "number_of_agents": 4, "execution_time": 18.5, "usage": { "input_tokens": 45, "output_tokens": 2100, "total_tokens": 2145, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.000146, "output_token_cost": 0.019425, "token_counts": { "total_input_tokens": 45, "total_output_tokens": 2100, "total_tokens": 2145 }, "num_agents": 4, "night_time_discount_applied": true }, "total_cost": 0.059571, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Design agents with clear, distinct specializations * Use for tasks that can be categorized and routed * Ensure agents have complementary capabilities * Ideal for customer service and support workflows # Multi-Agent Overview Source: https://docs.swarms.ai/docs/documentation/multi-agent/overview Comprehensive guide to multi-agent systems, swarm types, best practices, and the Swarm Completions API endpoint The Swarms API provides powerful multi-agent orchestration capabilities, enabling you to build complex systems where multiple AI agents collaborate to solve problems. Each multi-agent architecture type is designed for specific use cases and can be combined to create powerful multi-agent systems. ## Swarm Completions Endpoint The `/v1/swarm/completions` endpoint is the primary API for executing multi-agent swarm workflows. This endpoint supports both standard and streaming responses, allowing you to orchestrate complex multi-agent systems. **Endpoint**: `POST /v1/swarm/completions` **Base URL**: `https://api.swarms.world` ### Authentication All requests require an API key in the header: ``` x-api-key: your_api_key_here ``` ### Input Parameters The request body uses the `SwarmSpec` schema. All parameters are organized in the tables below: #### Swarm Configuration Parameters | Parameter | Type | Required | Default | Description | | --------------------------------------- | ------------------------- | -------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `string` | No | - | The name of the swarm, which serves as an identifier for the group of agents and their collective task. Maximum length: 100 characters. | | `description` | `string` | No | - | A comprehensive description of the swarm's objectives, capabilities, and intended outcomes. | | `swarm_type` | `string` | No | - | The classification of the swarm, indicating its operational style and methodology. See Swarm Architectures table below for available values. | | `max_loops` | `integer` | No | `1` | The maximum number of execution loops allowed for the swarm, enabling repeated processing if needed. | | `task` | `string` | No | - | The specific task or objective that the swarm is designed to accomplish. | | `tasks` | `array[string]` | No | - | A list of tasks that the swarm should complete. Used for workflows that handle multiple tasks. | | `agents` | `array[AgentSpec]` | No | - | A list of agents or specifications that define the agents participating in the swarm. See Agent Configuration table below. | | `rearrange_flow` | `string` | No | - | Instructions on how to rearrange the flow of tasks among agents, if applicable. Used with `AgentRearrange` swarm type. | | `messages` | `array[object] \| object` | No | - | A list of messages or a message object that the swarm should process. Used for conversational workflows like `GroupChat`. | | `img` | `string` | No | - | An optional image URL that may be associated with the swarm's task or representation. | | `stream` | `boolean` | No | `false` | A flag indicating whether the swarm should stream its output in real-time. | | `multi_agent_collab_prompt` | `boolean` | No | `true` | Inject the multi-agent collaboration prompt so agents coordinate with one another. Set to `false` to disable. | | `list_all_agents` | `boolean` | No | `false` | Whether to list all agents and their descriptions to one another so each agent is aware of the others. | | `heavy_swarm_question_agent_model_name` | `string` | No | `"gpt-4.1"` | For `HeavySwarm`: the model name to use for the question agent. | | `heavy_swarm_worker_model_name` | `string` | No | `"claude-sonnet-4-20250514"` | For `HeavySwarm`: the model name to use for the worker agent. | | `heavy_swarm_max_loops` | `integer` | No | `1` | For `HeavySwarm`: the maximum number of loops each agent in the heavy swarm may run. | | `heavy_swarm_variant` | `string` | No | `"default"` | For `HeavySwarm`: which agent variant to run. One of `"default"`, `"medium"`, or `"heavy"`. | | `council_judge_model_name` | `string` | No | `"gpt-5.4"` | For `CouncilAsAJudge`: the model name used by the judge that delivers the final ruling. | | `chairman_model` | `string` | No | `"gpt-5.1"` | For `LLMCouncil`: the model name used by the chairman that synthesizes the council's responses. | | `director_model_name` | `string` | No | `"gpt-5.4"` | The model name used by the director/overseer agent. For `HierarchicalSwarm`, this is the model that decomposes the task and delegates to workers. | | `director_settings` | `object` | No | `{}` | Optional settings for the director agent, such as `temperature`, `top_p`, and `max_tokens`. For `HierarchicalSwarm`, these tune the director's planning behavior. | #### Agent Configuration Parameters (AgentSpec) Each agent in the `agents` array can be configured with the following parameters: | Parameter | Type | Required | Default | Description | | ----------------------------- | ------------------------- | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `agent_name` | `string` | No | - | The unique name assigned to the agent, which identifies its role and functionality within the swarm. | | `description` | `string` | No | - | A detailed explanation of the agent's purpose, capabilities, and any specific tasks it is designed to perform. | | `system_prompt` | `string` | No | - | The initial instruction or context provided to the agent, guiding its behavior and responses during execution. | | `marketplace_prompt_id` | `string` | No | - | The ID of a prompt from the Swarms marketplace to use as the system prompt. If provided, the prompt will be automatically retrieved from the marketplace. | | `model_name` | `string` | No | `"claude-sonnet-5"` | The name of the AI model that the agent will utilize for processing tasks and generating outputs. Examples: `gpt-4o`, `gpt-4.1`, `openai/o3-mini`, `claude-sonnet-4-20250514`. | | `auto_generate_prompt` | `boolean` | No | `false` | A flag indicating whether the agent should automatically create prompts based on the task requirements. | | `max_tokens` | `integer` | No | `16000` | The maximum number of tokens that the agent is allowed to generate in its responses, limiting output length. Values below 1 are rejected with a 422 validation error. | | `temperature` | `number` | No | - | A parameter that controls the randomness of the agent's output; lower values result in more deterministic responses. If omitted, no temperature is sent to the model and the provider's own default applies. | | `role` | `string` | No | `"worker"` | The designated role of the agent within the swarm, which influences its behavior and interaction with other agents. | | `max_loops` | `integer \| string` | No | `1` | Maximum number of iterations the agent can perform for its task. Accepts an integer of 1 or greater for a fixed count, or `'auto'` to allow the system to determine the necessary number based on the task's complexity. Integer values below 1 are rejected with a 422 validation error. | | `tools_list_dictionary` | `array[object]` | No | - | A dictionary of tools that the agent can use to complete its task. | | `selected_tools` | `string \| array[string]` | No | All safe tools | Tools to enable for the autonomous looper when `max_loops="auto"`. Pass a list of tool names to restrict which tools the agent can use (e.g. `["think", "create_plan"]`). Available tools: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. Note: `run_bash` is not permitted for security reasons. | | `mcp_url` | `string` | No | - | The URL of the MCP server that the agent can use to complete its task. | | `mcp_config` | `object` | No | - | The MCP connection configuration to use for the agent. See MCP Connection Configuration table below. | | `mcp_configs` | `object` | No | - | Multiple MCP connections to use for the agent. This is a list of MCP connections. See Multiple MCP Connections below. | | `streaming_on` | `boolean` | No | `false` | A flag indicating whether the agent should stream its output. | | `llm_args` | `object` | No | - | Additional arguments to pass to the LLM such as `top_p`, `frequency_penalty`, `presence_penalty`, etc. | | `dynamic_temperature_enabled` | `boolean` | No | `false` | A flag indicating whether the agent should dynamically adjust its temperature based on the task. | | `tool_call_summary` | `boolean` | No | `true` | A parameter enabling an agent to summarize tool calls. | | `reasoning_effort` | `string` | No | - (unset) | The effort to put into reasoning. Options: `'none'`, `'minimal'`, `'low'`, `'medium'`, `'high'`, `'xhigh'`, `'ultra'`, `'max'`. Used with reasoning-enabled models. For Claude 5-family models (`claude-sonnet-5`, `claude-opus-5`, `claude-fable-5`) reasoning parameters are currently ignored and the agent runs without extended thinking. | | `thinking_tokens` | `integer` | No | - | The number of tokens to use for thinking. Used with reasoning-enabled models. | | `reasoning_enabled` | `boolean` | No | `false` | A parameter enabling an agent to use reasoning capabilities. | | `publish_to_marketplace` | `boolean` | No | `false` | A flag indicating whether to publish this agent to the Swarms marketplace. | | `use_cases` | `array[object]` | No | - | A list of use case dictionaries with `title` and `description` keys. Required when `publish_to_marketplace` is `true`. | | `tags` | `array[string]` | No | - | A list of searchable tags/keywords for the marketplace (e.g., `['finance', 'analysis']`). | | `capabilities` | `array[string]` | No | - | A list of agent capabilities or features (e.g., `['trend-analysis', 'risk-assessment']`). | | `category` | `string` | No | - | The marketplace category for the agent (e.g., `'research'`, `'content'`, `'coding'`, `'finance'`, `'healthcare'`, `'education'`, `'legal'`). | | `is_free` | `boolean` | No | `true` | A flag indicating whether the agent is free to use in the marketplace. | | `price_usd` | `number` | No | - | The price in USD for using this agent in the marketplace (if not free). | | `handoffs` | `array[AgentSpec]` | No | - | A list of agent specifications that this agent can hand off tasks to. These agents will be created and passed to the agent's handoffs parameter. | #### MCP Connection Configuration Parameters | Parameter | Type | Required | Default | Description | | --------------------- | --------- | -------- | ----------------------------- | ----------------------------------------------------------- | | `type` | `string` | No | `"mcp"` | The type of connection, defaults to `'mcp'`. | | `url` | `string` | No | `"http://localhost:8000/mcp"` | The URL endpoint for the MCP server. | | `tool_configurations` | `object` | No | - | Dictionary containing configuration settings for MCP tools. | | `authorization_token` | `string` | No | - | Authentication token for accessing the MCP server. | | `transport` | `string` | No | `"streamable_http"` | The transport protocol to use for the MCP server. | | `headers` | `object` | No | - | Headers to send to the MCP server. | | `timeout` | `integer` | No | `10` | Timeout for the MCP server in seconds. | #### Multiple MCP Connections | Parameter | Type | Required | Default | Description | | ------------- | ---------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------- | | `connections` | `array[MCPConnection]` | Yes | - | List of MCP connections. Each connection follows the MCP Connection Configuration schema above. | ### Output Parameters The endpoint returns a `SwarmCompletion` object with the following parameters: | Parameter | Type | Description | | ------------------ | --------- | --------------------------------------------------------------------------------------- | | `job_id` | `string` | The unique identifier for the swarm completion. | | `status` | `string` | The status of the swarm completion. | | `swarm_name` | `string` | The name of the swarm. | | `description` | `string` | The description of the swarm. | | `swarm_type` | `string` | The type of the swarm. | | `output` | `any` | The output of the swarm. Can be a string, array, or object depending on the swarm type. | | `number_of_agents` | `integer` | The number of agents in the swarm. | | `execution_time` | `number` | The execution time of the swarm in seconds. | | `usage` | `object` | Usage statistics including token counts and costs. | ## Swarm Architectures Each multi-agent architecture type is designed for specific use cases and can be combined to create powerful multi-agent systems. Below is a comprehensive table of all available swarm architectures with links to their detailed documentation: | Swarm Type | Description | Documentation | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | `AgentRearrange` | Dynamically reorganize agents to optimize task performance | [Learn More](/docs/documentation/multi-agent/agent_rearrange) | | `MixtureOfAgents` | Combine diverse specialist agents for complex tasks | [Learn More](/docs/documentation/multi-agent/mixture_of_agents) | | `SequentialWorkflow` | Executes tasks in a strict, predefined order | [Learn More](/docs/documentation/multi-agent/sequential_workflow) | | `ConcurrentWorkflow` | Runs independent tasks in parallel for higher throughput | [Learn More](/docs/documentation/multi-agent/concurrent_workflow) | | `MultiAgentRouter` | Intelligent dispatcher that routes tasks based on capabilities/load | [Learn More](/docs/documentation/multi-agent/multi_agent_router) | | `HierarchicalSwarm` | Multi-level structures with delegation and escalation | [Learn More](/docs/documentation/multi-agent/hierarchical_swarm) | | `MajorityVoting` | Consensus-based decision-making across multiple agents | [Learn More](/docs/documentation/multi-agent/majority_voting) | | `BatchedGridWorkflow` | Execute multiple tasks across multiple agents in a grid pattern | [Learn More](/docs/documentation/multi-agent/batched_grid_workflow) | | `GraphWorkflow` | Execute a graph workflow with directed agent nodes and edges (available via a dedicated `/v1/graph-workflow/completions` endpoint rather than the `swarm_type` field) | [Learn More](/docs/documentation/multi-agent/graph_workflow) | | `GroupChat` | Collaborative problem-solving through conversation | - | | `CouncilAsAJudge` | Council-based evaluation system | - | | `PlannerWorkerSwarm` | Separates planning from execution: planner agents break the task into sub-tasks that worker agents pull from a shared queue | - | | `HeavySwarm` | High-capacity swarm processing | [Learn More](/docs/documentation/multi-agent/heavy_swarm) | | `LLMCouncil` | Language model council for decisions | - | | `DebateWithJudge` | Structured debate with judgment | [Learn More](/docs/documentation/multi-agent/debate_with_judge) | | `RoundRobin` | Round-robin task distribution | [Learn More](/docs/documentation/multi-agent/round_robin) | | `auto` | Automatic swarm type selection | - | ## Best Practices This section outlines production-grade best practices for using the Swarms API effectively. These guidelines will help you choose the right swarm architecture, optimize costs, and implement robust error handling in your multi-agent systems. ### Choosing the Right Swarm Architecture Selecting the optimal swarm architecture is crucial for achieving your desired outcomes. Start by analyzing your task complexity: complex tasks benefit from `HierarchicalSwarm` or `MultiAgentRouter`. For dynamic tasks that require adaptive processing, consider `AgentRearrange`. When evaluating workflow patterns, use `SequentialWorkflow` for linear processes where each step depends on the previous one, `ConcurrentWorkflow` for parallel operations that can run independently, and `GroupChat` for collaborative tasks requiring interactive problem-solving. For multi-domain expertise requirements, `MixtureOfAgents` combines diverse specialist agents effectively, while `MajorityVoting` provides consensus-based decision-making for quality assurance needs. Different applications have specific swarm recommendations. Team automation systems excel with `HierarchicalSwarm`, providing automated team coordination with clear responsibility chains and scalable structures. Research pipelines benefit from `SequentialWorkflow`, ensuring structured processes with quality control at each stage. Trading systems leverage `ConcurrentWorkflow` for multi-market coverage and real-time analysis with risk distribution. Content factories utilize `MixtureOfAgents` for automated content creation with consistent quality and high throughput. Industry-specific patterns also guide architecture selection. In finance, risk analysis uses `HierarchicalSwarm`, market research employs `MixtureOfAgents`, and trading strategies leverage `ConcurrentWorkflow`. Healthcare applications use `SequentialWorkflow` for patient analysis, `MajorityVoting` for research review, `GroupChat` for treatment planning, and `MultiAgentRouter` for medical records management. Legal workflows apply `SequentialWorkflow` for document review, `MixtureOfAgents` for case analysis, `HierarchicalSwarm` for compliance checks, and `ConcurrentWorkflow` for contract analysis. ### Cost Optimization Effective cost management is essential for scaling your multi-agent systems. Batch processing, which groups related tasks together, can reduce costs by 20-30%. For Swarm Completions, scheduling non-urgent tasks during off-peak hours (8 PM - 6 AM PT) provides a 50% cost reduction on tokens. Token optimization through precise prompts and focused tasks yields 10-20% savings, while caching reusable results can reduce costs by 30-40%. Agent optimization by using the minimum required agents saves 15-25%, smart routing to specialized agents provides 10-15% savings, and prompt engineering to optimize input tokens delivers 15-20% cost reduction. When choosing service tiers, the standard tier is ideal for real-time processing, time-sensitive tasks, and critical workflows, offering immediate execution with higher priority and predictable timing, though at a higher cost with a 5-minute timeout. The off-peak tier for Swarm Completions is perfect for batch processing, non-urgent tasks, and cost-sensitive workloads, providing a 50% cost reduction on tokens during the 8 PM - 6 AM PT window, with the limitation that it only applies to Swarm Completions and has time window restrictions. ### Production Best Practices Implementing robust production practices ensures reliable and efficient multi-agent systems. Always use appropriate swarm types for your specific tasks, implement comprehensive error handling with retry logic, and monitor and log all executions to track performance and identify issues. Cache repeated results to reduce redundant processing, rotate API keys regularly for security, and choose the appropriate service tier based on task urgency. For Swarm Completions, schedule non-urgent tasks during off-peak hours (8 PM - 6 AM PT) to benefit from the night-time discount. Avoid common anti-patterns that can compromise your system's reliability and security. Never hardcode API keys in your application code, always respect rate limits to prevent service disruptions, and ensure error handling is implemented for all API calls. Avoid using excessive agent counts when fewer agents can accomplish the task, maintain adequate monitoring to track system health, and always implement retry logic for failed requests to handle transient failures gracefully. ### Error Handling Robust error handling is critical for production systems. For 400 errors (Input Validation), implement pre-request validation with fallback mechanisms to catch issues before they reach the API. Handle 401 errors (Auth Management) through secure key rotation and proper storage of credentials. When encountering 429 errors (Rate Limiting), implement exponential backoff with queuing to manage rate limit constraints. For 500 errors (Resilience), use retry mechanisms with circuit breaking to prevent cascading failures. Handle 503 errors (High Availability) with multi-region redundancy when possible, and manage 504 errors (Timeout Handling) with adaptive timeouts that can return partial results when appropriate. ### Performance Benchmarks Monitoring performance metrics helps ensure your multi-agent systems meet production standards. Target response times should be under 2 seconds, with warnings when exceeding 5 seconds. Maintain success rates above 99%, with alerts when dropping below 95%. Keep cost per task under \$0.05, with warnings when exceeding \$0.10. Aim for cache hit rates above 80%, with alerts when dropping below 60%. Error rates should remain under 1%, with warnings when exceeding 5%. Retry rates should stay under 10%, with alerts when exceeding 30%. These benchmarks help maintain optimal system performance and cost efficiency. ## Example Usage ### Basic Swarm Completion ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Team", "description": "Multi-agent research swarm", "swarm_type": "MixtureOfAgents", "task": "Analyze the impact of AI on healthcare", "agents": [ { "agent_name": "Research Analyst", "description": "Conducts comprehensive research", "system_prompt": "You are a research analyst specializing in healthcare technology.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 }' ``` ```python theme={null} import requests API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Research Team", "description": "Multi-agent research swarm", "swarm_type": "MixtureOfAgents", "task": "Analyze the impact of AI on healthcare", "agents": [ { "agent_name": "Research Analyst", "description": "Conducts comprehensive research", "system_prompt": "You are a research analyst specializing in healthcare technology.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) result = response.json() print(result) ``` ## Additional Resources * [API Dashboard](https://swarms.world/platform/api-keys) * [API Reference](https://docs.swarms.ai/api-reference) * [Getting Started Guide](/docs/documentation/getting-started/quickstart) # RoundRobin Source: https://docs.swarms.ai/docs/documentation/multi-agent/round_robin Randomized round-robin task distribution where agents take turns collaborating with full conversation context **Swarm Type**: `RoundRobin` ## Overview The RoundRobin swarm implements a collaborative communication pattern where agents take turns processing a task in a randomized round-robin fashion. Each loop, agents are shuffled into a random order and each receives the full conversation history, encouraging them to build upon and refine previous agents' contributions. This creates a natural collaborative dynamic similar to a brainstorming session. Key features: * **Randomized Turn Order**: Agents are shuffled each loop for varied interaction patterns * **Full Conversation Context**: Every agent sees the complete conversation history from prior agents * **Collaborative Prompting**: Built-in prompts encourage agents to acknowledge and extend others' contributions * **Iterative Refinement**: Multiple loops allow the group to progressively deepen their analysis * **Automatic Retries**: Exponential backoff retry logic for resilient agent execution ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A["Turn 1"] --> B["Turn 2"] --> C["Turn 3"] --> O["Result"] C -.->|"next loop, reshuffled"| A ``` Agents take turns, each reading the full conversation so far. The turn order is reshuffled at the start of every loop. ## Use Cases * Collaborative brainstorming and ideation sessions * Research synthesis from multiple domain experts * Code review with multiple engineering perspectives * Content creation with iterative editorial refinement * Strategic planning with cross-functional input ## API Usage ### Basic RoundRobin Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Market Strategy Roundtable", "description": "Collaborative market strategy discussion with round-robin agent turns", "swarm_type": "RoundRobin", "task": "Develop a go-to-market strategy for an AI-powered code review tool targeting mid-size engineering teams (20-100 developers). Cover positioning, pricing, channels, and competitive differentiation.", "agents": [ { "agent_name": "Product Strategist", "description": "Defines product positioning and value proposition", "system_prompt": "You are a product strategist. Define the core value proposition, target personas, and competitive positioning. Be specific about what differentiates this product from existing solutions like GitHub Copilot, Codacy, and SonarQube.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a growth marketing expert. Propose acquisition channels ranked by expected ROI, design the launch campaign, and suggest pricing tiers. Be data-driven with estimated CAC and conversion benchmarks.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Sales Engineer", "description": "Evaluates technical feasibility and enterprise readiness", "system_prompt": "You are a sales engineer. Evaluate the enterprise sales motion, identify technical integration requirements, and propose a proof-of-concept framework. Focus on what mid-size teams need for adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Market Strategy Roundtable", "description": "Collaborative market strategy discussion with round-robin agent turns", "swarm_type": "RoundRobin", "task": "Develop a go-to-market strategy for an AI-powered code review tool targeting mid-size engineering teams (20-100 developers). Cover positioning, pricing, channels, and competitive differentiation.", "agents": [ { "agent_name": "Product Strategist", "description": "Defines product positioning and value proposition", "system_prompt": "You are a product strategist. Define the core value proposition, target personas, and competitive positioning. Be specific about what differentiates this product from existing solutions like GitHub Copilot, Codacy, and SonarQube.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a growth marketing expert. Propose acquisition channels ranked by expected ROI, design the launch campaign, and suggest pricing tiers. Be data-driven with estimated CAC and conversion benchmarks.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Sales Engineer", "description": "Evaluates technical feasibility and enterprise readiness", "system_prompt": "You are a sales engineer. Evaluate the enterprise sales motion, identify technical integration requirements, and propose a proof-of-concept framework. Focus on what mid-size teams need for adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print(json.dumps(result["output"], indent=2)) else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Market Strategy Roundtable", description: "Collaborative market strategy discussion with round-robin agent turns", swarm_type: "RoundRobin", task: "Develop a go-to-market strategy for an AI-powered code review tool targeting mid-size engineering teams (20-100 developers). Cover positioning, pricing, channels, and competitive differentiation.", agents: [ { agent_name: "Product Strategist", description: "Defines product positioning and value proposition", system_prompt: "You are a product strategist. Define the core value proposition, target personas, and competitive positioning. Be specific about what differentiates this product from existing solutions like GitHub Copilot, Codacy, and SonarQube.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.5 }, { agent_name: "Growth Marketer", description: "Designs acquisition channels and launch campaigns", system_prompt: "You are a growth marketing expert. Propose acquisition channels ranked by expected ROI, design the launch campaign, and suggest pricing tiers. Be data-driven with estimated CAC and conversion benchmarks.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.5 }, { agent_name: "Sales Engineer", description: "Evaluates technical feasibility and enterprise readiness", system_prompt: "You are a sales engineer. Evaluate the enterprise sales motion, identify technical integration requirements, and propose a proof-of-concept framework. Focus on what mid-size teams need for adoption.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("RoundRobin swarm completed successfully!"); console.log("Output:", JSON.stringify(result.output, null, 2)); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Market Strategy Roundtable", Description: "Collaborative market strategy discussion with round-robin agent turns", SwarmType: "RoundRobin", Task: "Develop a go-to-market strategy for an AI-powered code review tool targeting mid-size engineering teams (20-100 developers). Cover positioning, pricing, channels, and competitive differentiation.", Agents: []Agent{ { AgentName: "Product Strategist", Description: "Defines product positioning and value proposition", SystemPrompt: "You are a product strategist. Define the core value proposition, target personas, and competitive positioning. Be specific about what differentiates this product from existing solutions like GitHub Copilot, Codacy, and SonarQube.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Growth Marketer", Description: "Designs acquisition channels and launch campaigns", SystemPrompt: "You are a growth marketing expert. Propose acquisition channels ranked by expected ROI, design the launch campaign, and suggest pricing tiers. Be data-driven with estimated CAC and conversion benchmarks.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.5, }, { AgentName: "Sales Engineer", Description: "Evaluates technical feasibility and enterprise readiness", SystemPrompt: "You are a sales engineer. Evaluate the enterprise sales motion, identify technical integration requirements, and propose a proof-of-concept framework. Focus on what mid-size teams need for adoption.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Market Strategy Roundtable", "description": "Collaborative market strategy discussion with round-robin agent turns", "swarm_type": "RoundRobin", "task": "Develop a go-to-market strategy for an AI-powered code review tool targeting mid-size engineering teams (20-100 developers). Cover positioning, pricing, channels, and competitive differentiation.", "agents": [ { "agent_name": "Product Strategist", "description": "Defines product positioning and value proposition", "system_prompt": "You are a product strategist. Define the core value proposition, target personas, and competitive positioning. Be specific about what differentiates this product from existing solutions like GitHub Copilot, Codacy, and SonarQube.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": "You are a growth marketing expert. Propose acquisition channels ranked by expected ROI, design the launch campaign, and suggest pricing tiers. Be data-driven with estimated CAC and conversion benchmarks.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Sales Engineer", "description": "Evaluates technical feasibility and enterprise readiness", "system_prompt": "You are a sales engineer. Evaluate the enterprise sales motion, identify technical integration requirements, and propose a proof-of-concept framework. Focus on what mid-size teams need for adoption.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("RoundRobin swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-R82kLFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Market Strategy Roundtable", "description": "Collaborative market strategy discussion with round-robin agent turns", "swarm_type": "RoundRobin", "output": [ { "role": "Product Strategist", "content": "Our core value proposition centers on 'AI-native code review that understands your codebase, not just syntax.' Unlike GitHub Copilot (focused on generation) or SonarQube (static analysis), we combine deep codebase understanding with contextual review that catches architectural issues, not just linting errors..." }, { "role": "Growth Marketer", "content": "Building on the Product Strategist's positioning, here's the channel strategy: 1) Developer communities (Dev.to, Hacker News launches) - lowest CAC at $15-25. 2) GitHub Marketplace listing - organic discovery channel. 3) Content marketing targeting 'code review best practices' keywords..." }, { "role": "Sales Engineer", "content": "Acknowledging the positioning and channel strategy above, here's the enterprise readiness assessment: Integration requirements include GitHub/GitLab webhooks, SSO via SAML/OIDC, and a 15-minute POC setup. For mid-size teams, the key adoption blocker is proving value in the first PR review..." } ], "number_of_agents": 3, "execution_time": 32.6, "usage": { "input_tokens": 45, "output_tokens": 2400, "total_tokens": 2445, "billing_info": { "cost_breakdown": { "agent_cost": 0.03, "input_token_cost": 0.000293, "output_token_cost": 0.0444, "token_counts": { "total_input_tokens": 45, "total_output_tokens": 2400, "total_tokens": 2445 }, "num_agents": 3, "night_time_discount_applied": false }, "total_cost": 0.074692, "discount_active": false, "discount_type": "none", "discount_percentage": 0 } } } ``` ## Best Practices * Use 3-5 agents for optimal collaboration — too many agents dilute the conversation context * Each agent should have a clearly distinct expertise so contributions don't overlap * Increase `max_loops` when you want agents to iterate and refine each other's ideas across multiple rounds * Agent order is randomized each loop, so design prompts that work regardless of speaking position * Ideal for tasks where diverse perspectives and iterative refinement produce better results than parallel independent work # SequentialWorkflow Source: https://docs.swarms.ai/docs/documentation/multi-agent/sequential_workflow Execute tasks in a strict, predefined order for step-by-step processing with dependencies between steps **Swarm Type**: `SequentialWorkflow` ## Overview The SequentialWorkflow swarm type executes tasks in a strict, predefined order where each step depends on the completion of the previous one. This architecture is perfect for workflows that require a linear progression of tasks, ensuring that each agent builds upon the work of the previous agent. Key features: * **Ordered Execution**: Agents execute in a specific, predefined sequence * **Step Dependencies**: Each step builds upon previous results * **Predictable Flow**: Clear, linear progression through the workflow * **Quality Control**: Each agent can validate and enhance previous work ## Architecture ```mermaid theme={null} flowchart LR T["Task"] --> A1["Agent 1"] --> A2["Agent 2"] --> A3["Agent 3"] --> R["Result"] ``` Each agent runs only after the previous one finishes, and receives its output. ## Use Cases * Document processing pipelines * Multi-stage analysis workflows * Content creation and editing processes * Data transformation and validation pipelines ## API Usage ### Basic SequentialWorkflow Example ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Content Creation Pipeline", "description": "Sequential content creation from research to final output", "swarm_type": "SequentialWorkflow", "task": "Create a comprehensive blog post about the future of renewable energy", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts thorough research on the topic", "system_prompt": "You are a research specialist. Gather comprehensive, accurate information on the given topic from reliable sources.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Content Writer", "description": "Creates engaging written content", "system_prompt": "You are a skilled content writer. Transform research into engaging, well-structured articles that are informative and readable.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6 }, { "agent_name": "Editor", "description": "Reviews and polishes the content", "system_prompt": "You are a professional editor. Review content for clarity, grammar, flow, and overall quality. Make improvements while maintaining the author's voice.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "SEO Optimizer", "description": "Optimizes content for search engines", "system_prompt": "You are an SEO expert. Optimize content for search engines while maintaining readability and quality.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 }' ``` ```python theme={null} import requests import json API_BASE_URL = "https://api.swarms.world" API_KEY = "your_api_key_here" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } swarm_config = { "name": "Content Creation Pipeline", "description": "Sequential content creation from research to final output", "swarm_type": "SequentialWorkflow", "task": "Create a comprehensive blog post about the future of renewable energy", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts thorough research on the topic", "system_prompt": "You are a research specialist. Gather comprehensive, accurate information on the given topic from reliable sources.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Content Writer", "description": "Creates engaging written content", "system_prompt": "You are a skilled content writer. Transform research into engaging, well-structured articles that are informative and readable.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6 }, { "agent_name": "Editor", "description": "Reviews and polishes the content", "system_prompt": "You are a professional editor. Review content for clarity, grammar, flow, and overall quality. Make improvements while maintaining the author's voice.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "SEO Optimizer", "description": "Optimizes content for search engines", "system_prompt": "You are an SEO expert. Optimize content for search engines while maintaining readability and quality.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config ) if response.status_code == 200: result = response.json() print("SequentialWorkflow swarm completed successfully!") print(f"Cost: ${result['usage']['billing_info']['total_cost']}") print(f"Execution time: {result['execution_time']} seconds") print(f"Sequential results: {result['output']}") else: print(f"Error: {response.status_code} - {response.text}") ``` ```javascript theme={null} const API_BASE_URL = "https://api.swarms.world"; const API_KEY = "your_api_key_here"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const swarmConfig = { name: "Content Creation Pipeline", description: "Sequential content creation from research to final output", swarm_type: "SequentialWorkflow", task: "Create a comprehensive blog post about the future of renewable energy", agents: [ { agent_name: "Research Specialist", description: "Conducts thorough research on the topic", system_prompt: "You are a research specialist. Gather comprehensive, accurate information on the given topic from reliable sources.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.3 }, { agent_name: "Content Writer", description: "Creates engaging written content", system_prompt: "You are a skilled content writer. Transform research into engaging, well-structured articles that are informative and readable.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.6 }, { agent_name: "Editor", description: "Reviews and polishes the content", system_prompt: "You are a professional editor. Review content for clarity, grammar, flow, and overall quality. Make improvements while maintaining the author's voice.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.4 }, { agent_name: "SEO Optimizer", description: "Optimizes content for search engines", system_prompt: "You are an SEO expert. Optimize content for search engines while maintaining readability and quality.", model_name: "gpt-4.1", max_loops: 1, temperature: 0.2 } ], max_loops: 1 }; fetch(`${API_BASE_URL}/v1/swarm/completions`, { method: "POST", headers: headers, body: JSON.stringify(swarmConfig) }) .then(response => response.json()) .then(result => { if (result.status === "success") { console.log("SequentialWorkflow swarm completed successfully!"); console.log(`Cost: $${result.usage.billing_info.total_cost}`); console.log(`Execution time: ${result.execution_time} seconds`); console.log("Sequential results:", result.output); } }) .catch(error => console.error("Error:", error)); ``` ```go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) type Agent struct { AgentName string `json:"agent_name"` Description string `json:"description"` SystemPrompt string `json:"system_prompt"` ModelName string `json:"model_name"` MaxLoops int `json:"max_loops"` Temperature float64 `json:"temperature"` } type SwarmConfig struct { Name string `json:"name"` Description string `json:"description"` SwarmType string `json:"swarm_type"` Task string `json:"task"` Agents []Agent `json:"agents"` MaxLoops int `json:"max_loops"` } func main() { API_BASE_URL := "https://api.swarms.world" API_KEY := "your_api_key_here" swarmConfig := SwarmConfig{ Name: "Content Creation Pipeline", Description: "Sequential content creation from research to final output", SwarmType: "SequentialWorkflow", Task: "Create a comprehensive blog post about the future of renewable energy", Agents: []Agent{ { AgentName: "Research Specialist", Description: "Conducts thorough research on the topic", SystemPrompt: "You are a research specialist. Gather comprehensive, accurate information on the given topic from reliable sources.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.3, }, { AgentName: "Content Writer", Description: "Creates engaging written content", SystemPrompt: "You are a skilled content writer. Transform research into engaging, well-structured articles that are informative and readable.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.6, }, { AgentName: "Editor", Description: "Reviews and polishes the content", SystemPrompt: "You are a professional editor. Review content for clarity, grammar, flow, and overall quality. Make improvements while maintaining the author's voice.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.4, }, { AgentName: "SEO Optimizer", Description: "Optimizes content for search engines", SystemPrompt: "You are an SEO expert. Optimize content for search engines while maintaining readability and quality.", ModelName: "gpt-4.1", MaxLoops: 1, Temperature: 0.2, }, }, MaxLoops: 1, } jsonData, _ := json.Marshal(swarmConfig) req, _ := http.NewRequest("POST", API_BASE_URL+"/v1/swarm/completions", bytes.NewBuffer(jsonData)) req.Header.Set("x-api-key", API_KEY) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Error: %v\n", err) return } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Response: %s\n", string(body)) } ``` ```rust theme={null} use reqwest::Client; use serde_json::{json, Value}; use std::error::Error; #[tokio::main] async fn main() -> Result<(), Box> { let api_base_url = "https://api.swarms.world"; let api_key = "your_api_key_here"; let swarm_config = json!({ "name": "Content Creation Pipeline", "description": "Sequential content creation from research to final output", "swarm_type": "SequentialWorkflow", "task": "Create a comprehensive blog post about the future of renewable energy", "agents": [ { "agent_name": "Research Specialist", "description": "Conducts thorough research on the topic", "system_prompt": "You are a research specialist. Gather comprehensive, accurate information on the given topic from reliable sources.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Content Writer", "description": "Creates engaging written content", "system_prompt": "You are a skilled content writer. Transform research into engaging, well-structured articles that are informative and readable.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6 }, { "agent_name": "Editor", "description": "Reviews and polishes the content", "system_prompt": "You are a professional editor. Review content for clarity, grammar, flow, and overall quality. Make improvements while maintaining the author's voice.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "SEO Optimizer", "description": "Optimizes content for search engines", "system_prompt": "You are an SEO expert. Optimize content for search engines while maintaining readability and quality.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 }); let client = Client::new(); let response = client .post(&format!("{}/v1/swarm/completions", api_base_url)) .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&swarm_config) .send() .await?; if response.status().is_success() { let result: Value = response.json().await?; println!("SequentialWorkflow swarm completed successfully!"); println!("Response: {:?}", result); } else { println!("Error: {}", response.status()); } Ok(()) } ``` **Example Response**: ```json theme={null} { "job_id": "swarms-S17nZFDesmLHxCRoeyF3NVYvPaXk", "status": "success", "swarm_name": "Content Creation Pipeline", "description": "Sequential content creation from research to final output", "swarm_type": "SequentialWorkflow", "output": [ { "role": "Research Specialist", "content": "Based on my research on renewable energy, here are the key findings about the future of this sector..." }, { "role": "Content Writer", "content": "Building on the research, here's a comprehensive blog post about the future of renewable energy..." }, { "role": "Editor", "content": "After reviewing the content, I've made the following improvements for clarity and flow..." }, { "role": "SEO Optimizer", "content": "I've optimized the content with the following SEO improvements while maintaining quality..." } ], "number_of_agents": 4, "execution_time": 45.2, "usage": { "input_tokens": 35, "output_tokens": 3200, "total_tokens": 3235, "billing_info": { "cost_breakdown": { "agent_cost": 0.04, "input_token_cost": 0.000114, "output_token_cost": 0.0296, "token_counts": { "total_input_tokens": 35, "total_output_tokens": 3200, "total_tokens": 3235 }, "num_agents": 4, "night_time_discount_applied": true }, "total_cost": 0.069714, "discount_active": true, "discount_type": "night_time", "discount_percentage": 50 } } } ``` ## Best Practices * Design workflows with clear dependencies between steps * Use for tasks that require sequential processing * Ensure each agent builds upon previous results effectively * Ideal for quality control and validation workflows # Swarm Completions Reference Source: https://docs.swarms.ai/docs/documentation/multi-agent/swarm_completions Complete reference for POST /v1/swarm/completions — the full SwarmSpec and AgentSpec schemas, every swarm_type, architecture-specific parameters, MCP configuration, response shape, and error handling. `POST /v1/swarm/completions` is the primary endpoint of the Swarms API. One request describes a whole multi-agent system — the roster, the architecture that coordinates it, and the task — and the response returns the swarm's output along with timing and usage. This page is the complete field-by-field reference. For a conceptual introduction, start with [Multi-Agent Overview](/docs/documentation/multi-agent/overview); for guidance on picking a topology, see [Available Architectures](/docs/documentation/multi-agent/available-architectures). ## Endpoint | Property | Value | | ------------------ | ----------------------------- | | **Method** | `POST` | | **Path** | `/v1/swarm/completions` | | **Base URL** | `https://api.swarms.world` | | **Request body** | `SwarmSpec` (required) | | **Response body** | `SwarmCompletion` | | **Authentication** | `x-api-key` header (required) | | **Streaming** | Supported via `stream: true` | | **Tier** | Available on all tiers | ### Authentication Every request requires your API key in the `x-api-key` header. Get one from the [API Keys page](https://swarms.world/platform/api-keys). ```bash theme={null} x-api-key: YOUR_API_KEY Content-Type: application/json ``` The batch variant, [`/v1/swarm/batch/completions`](/docs/examples/examples/batch-swarm-completions), accepts an array of these same `SwarmSpec` objects (at most 50 per request) and is premium-gated. The single endpoint documented here is not. *** ## Request Body: SwarmSpec Every field is optional at the schema level, but a request with no `task` (or `tasks`/`messages`) and no `agents` has nothing to run. In practice you always send `agents`, `swarm_type`, and a task. ### Core Parameters | Parameter | Type | Default | Constraints | Description | | --------------------------- | --------------------------------- | ------- | ------------------------------------- | ------------------------------------------------------------------------------------------------- | | `name` | `string \| null` | — | max 100 chars | Identifier for the group of agents and their collective task | | `description` | `string \| null` | — | — | Description of the swarm's objectives, capabilities, and intended outcomes | | `agents` | `array[AgentSpec] \| null` | — | **max 2000 items** | The agents participating in the swarm. See [AgentSpec](#agentspec) | | `swarm_type` | `string \| null` | — | enum, see [Swarm Types](#swarm-types) | The architecture that coordinates the agents | | `max_loops` | `integer \| null` | `1` | **max 50** | Maximum execution loops for the swarm | | `task` | `string \| null` | — | — | The specific task the swarm is designed to accomplish | | `tasks` | `array[string] \| null` | — | — | A list of tasks. Used by architectures that consume multiple tasks, such as `BatchedGridWorkflow` | | `messages` | `array[object] \| object \| null` | — | — | Message history for conversational workflows such as `GroupChat` | | `img` | `string \| null` | — | — | Optional image URL associated with the task, for vision-enabled agents | | `stream` | `boolean \| null` | `false` | — | Stream the swarm's output instead of buffering it | | `multi_agent_collab_prompt` | `boolean \| null` | `true` | — | Inject the multi-agent collaboration prompt so agents coordinate. Set `false` to disable | | `list_all_agents` | `boolean \| null` | `false` | — | Show every agent's name and description to the others, so each is aware of the roster | `agents` accepts up to **2000** entries and `max_loops` is capped at **50**. Exceeding either returns a `422` validation error before any work is billed. ### Architecture-Specific Parameters These only take effect for their corresponding `swarm_type`. Sending them with a different architecture is harmless but has no effect. | Parameter | Type | Default | Applies to | Description | | --------------------------------------- | ----------------- | ---------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `rearrange_flow` | `string \| null` | — | `AgentRearrange` | How tasks flow between agents. `->` is a handoff, a comma runs agents in parallel within a step. **Required** for this type | | `heavy_swarm_question_agent_model_name` | `string \| null` | `"gpt-4.1"` | `HeavySwarm` | Model backing the question-generation agent | | `heavy_swarm_worker_model_name` | `string \| null` | `"claude-sonnet-4-20250514"` | `HeavySwarm` | Model backing the four worker agents | | `heavy_swarm_max_loops` | `integer \| null` | `1` | `HeavySwarm` | Maximum loops each agent in the heavy swarm may run | | `heavy_swarm_variant` | `string \| null` | `"default"` | `HeavySwarm` | Agent variant to run. One of `"default"`, `"medium"`, `"heavy"` | | `council_judge_model_name` | `string \| null` | `"gpt-5.4"` | `CouncilAsAJudge` | Model used by the judge that delivers the final ruling | | `chairman_model` | `string \| null` | `"gpt-5.1"` | `LLMCouncil` | Model used by the chairman that synthesizes the council's responses | | `director_model_name` | `string \| null` | `"gpt-5.4"` | `HierarchicalSwarm` | Model used by the director/overseer that decomposes and delegates | | `director_settings` | `object \| null` | — | `HierarchicalSwarm` | Hyperparameters for the director agent — `temperature`, `top_p`, `max_tokens`, and similar | ### Swarm Types `swarm_type` accepts one of the following 16 values: | Value | Coordination pattern | Reference | | --------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------ | | `SequentialWorkflow` | Linear chain, each agent fed the previous output | [Docs](/docs/documentation/multi-agent/sequential_workflow) | | `ConcurrentWorkflow` | All agents run in parallel on independent work | [Docs](/docs/documentation/multi-agent/concurrent_workflow) | | `AgentRearrange` | Custom flow defined by `rearrange_flow` | [Docs](/docs/documentation/multi-agent/agent_rearrange) | | `MixtureOfAgents` | Specialists on the same task, perspectives combined | [Docs](/docs/documentation/multi-agent/mixture_of_agents) | | `MultiAgentRouter` | Dispatcher routes the task to the best-suited agent | [Docs](/docs/documentation/multi-agent/multi_agent_router) | | `HierarchicalSwarm` | Director delegates to workers, then reviews | [Docs](/docs/documentation/multi-agent/hierarchical_swarm) | | `MajorityVoting` | Independent votes reconciled by majority | [Docs](/docs/documentation/multi-agent/majority_voting) | | `GroupChat` | Shared conversation between agents | [Docs](/docs/documentation/multi-agent/group_chat) | | `RoundRobin` | Agents take turns on a reshuffled order | [Docs](/docs/documentation/multi-agent/round_robin) | | `DebateWithJudge` | Pro and Con debate, a judge synthesizes | [Docs](/docs/documentation/multi-agent/debate_with_judge) | | `HeavySwarm` | Question decomposition, four specialists, synthesis | [Docs](/docs/documentation/multi-agent/heavy_swarm) | | `BatchedGridWorkflow` | Every agent runs every task, producing a matrix | [Docs](/docs/documentation/multi-agent/batched_grid_workflow) | | `CouncilAsAJudge` | A council evaluates and a judge rules | [Example](/docs/examples/examples/council-as-judge) | | `LLMCouncil` | Council deliberates, a chairman synthesizes | [Example](/docs/examples/examples/llm-council) | | `PlannerWorkerSwarm` | Planner decomposes, workers pull from a shared queue | [Architectures](/docs/documentation/multi-agent/available-architectures) | | `auto` | The API selects an architecture based on the task | — | `BatchedGridWorkflow` also has a dedicated premium endpoint, `/v1/batched-grid-workflow/completions`, and `GraphWorkflow` is **not** a `swarm_type` at all — it has its own endpoint at [`/v1/graph-workflow/completions`](/docs/documentation/multi-agent/graph_workflow). *** ## AgentSpec Each entry in `agents` is an `AgentSpec`. Every field is optional. ### Identity and Model | Parameter | Type | Default | Description | | ----------------------- | ----------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `agent_name` | `string \| null` | — | Unique name identifying the agent's role within the swarm | | `description` | `string \| null` | — | Explanation of the agent's purpose and capabilities | | `system_prompt` | `string \| null` | — | Initial instruction guiding the agent's behavior | | `marketplace_prompt_id` | `string \| null` | — | ID of a [marketplace prompt](/docs/marketplace/prompts-api) to use as the system prompt, retrieved automatically | | `model_name` | `string \| null` | `"claude-sonnet-5"` | The model the agent uses. For example `gpt-4o`, `gpt-4.1`, `openai/o3-mini` | | `fallback_models` | `array[string] \| null` | — | Ordered list of models to retry on failure. If set while `model_name` is omitted, the first entry becomes the primary model | | `fallback_model_name` | `string \| null` | — | A single fallback model, tried **after** any `fallback_models` | | `role` | `string \| null` | `"worker"` | The agent's designated role, which influences behavior and interaction | ### Generation Controls | Parameter | Type | Default | Constraints | Description | | ----------------------------- | ----------------- | ------- | ----------- | ----------------------------------------------------------------------------------------- | | `max_tokens` | `integer \| null` | `16000` | **min 1** | Maximum tokens the agent may generate | | `temperature` | `number \| null` | — | **0 to 2** | Randomness control. If omitted, no temperature is sent and the provider's default applies | | `top_p` | `number \| null` | — | — | The `top_p` value passed to the model | | `llm_args` | `object \| null` | — | — | Additional model arguments such as `frequency_penalty` and `presence_penalty` | | `dynamic_temperature_enabled` | `boolean \| null` | `false` | — | Let the agent adjust its own temperature based on the task | | `auto_generate_prompt` | `boolean \| null` | `false` | — | Have the agent write its own prompt from the task requirements | | `streaming_on` | `boolean \| null` | `false` | — | Stream this agent's output | ### Looping and Tools | Parameter | Type | Default | Description | | ----------------------- | --------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------ | | `max_loops` | `integer \| string \| null` | `1` | Iterations for this agent. An integer **1 to 50**, or `"auto"` to let the system decide from task complexity | | `tools_list_dictionary` | `array[object] \| null` | — | Tool definitions the agent can call | | `selected_tools` | `string \| array[string] \| null` | all safe defaults | Restricts which tools the autonomous looper may use when `max_loops="auto"` | | `tool_call_summary` | `boolean \| null` | `true` | Have the agent summarize its tool calls | | `mcp_url` | `string \| null` | — | URL of an MCP server the agent can use | | `mcp_config` | `MCPConnection \| null` | — | A single MCP connection. See [MCPConnection](#mcpconnection) | | `mcp_configs` | `MultipleMCPConnections \| null` | — | Several MCP connections at once | | `handoffs` | `array[AgentSpec] \| null` | — | Agents this agent can hand tasks to. These are created and attached as its handoff targets | `selected_tools` accepts: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. **`run_bash` is not permitted.** ### Reasoning | Parameter | Type | Default | Description | | ------------------- | ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ | | `reasoning_enabled` | `boolean \| null` | `false` | Enable extended reasoning for this agent | | `reasoning_effort` | `string \| null` | — | One of `minimal`, `low`, `medium`, `high`, `none`, `xhigh`, `ultra`, `max`. `max` is the deepest tier and needs no beta header | | `thinking_tokens` | `integer \| null` | — | Tokens budgeted for thinking | At `xhigh` and above, pair `reasoning_effort` with a large `max_tokens` so the model has room to both think and answer. A low `max_tokens` at high effort produces truncated or empty output. ### Marketplace Publishing Set when you want the agent listed on the [Swarms Marketplace](/docs/marketplace/agents-api) as a side effect of the run. | Parameter | Type | Default | Description | | ------------------------ | ----------------------- | ------- | --------------------------------------------------------------------------------------------------------- | | `publish_to_marketplace` | `boolean \| null` | `false` | Publish this agent to the marketplace | | `use_cases` | `array[object] \| null` | — | Dictionaries with `title` and `description`. **Required** when publishing | | `tags` | `array[string] \| null` | — | Searchable keywords, e.g. `["finance", "analysis"]` | | `capabilities` | `array[string] \| null` | — | Feature list, e.g. `["trend-analysis", "risk-assessment"]` | | `category` | `string \| null` | — | Marketplace category, e.g. `research`, `content`, `coding`, `finance`, `healthcare`, `education`, `legal` | | `is_free` | `boolean \| null` | `true` | Whether the agent is free to use | | `price_usd` | `number \| null` | — | Price in USD when not free | *** ## MCPConnection Passed as `mcp_config` on an `AgentSpec`. Accepts additional properties beyond those listed. | Parameter | Type | Default | Description | | --------------------- | ----------------- | ----------------------------- | ---------------------------------------------------------------------------------------- | | `type` | `string \| null` | `"mcp"` | Connection type | | `url` | `string \| null` | `"http://localhost:8000/mcp"` | The MCP server endpoint | | `name` | `string \| null` | — | Human-readable server name, used in logs and tool routing | | `transport` | `string \| null` | `"streamable_http"` | One of `streamable_http`, `sse`, `stdio`, `auto` | | `tool_configurations` | `object \| null` | — | Configuration settings for MCP tools | | `headers` | `object \| null` | — | Headers sent to the MCP server | | `timeout` | `integer \| null` | `30` | Request timeout in seconds | | `sse_read_timeout` | `integer \| null` | `300` | How long to wait for streamed events before giving up | | `tool_timeout` | `integer \| null` | `120` | How long a single tool call may run. Separate from `timeout`, which bounds HTTP requests | ### MCP Authentication | Parameter | Type | Default | Description | | --------------------- | ------------------------ | ----------------- | --------------------------------------------------------------------------------------------------------------- | | `auth_type` | `string \| null` | inferred | Explicit auth mode: `none`, `api_key`, `bearer`, `oauth`, `custom`. Inferred from the other fields when omitted | | `authorization_token` | `string \| null` | — | Bearer token for the MCP server | | `api_key` | `string \| null` | — | API key, sent using `api_key_header` and `api_key_prefix` | | `api_key_header` | `string` | `"Authorization"` | Header used to send the API key, e.g. `X-API-Key` | | `api_key_prefix` | `string \| null` | `"Bearer"` | Prefix prepended to the key. Set to `null` or `""` for raw keys | | `oauth` | `MCPOAuthConfig \| null` | — | OAuth 2.1 configuration. See [MCPOAuthConfig](#mcpoauthconfig) | ### stdio Transport Only used when `transport` is `"stdio"`. | Parameter | Type | Description | | --------- | ----------------------- | ------------------------------------- | | `command` | `string \| null` | Executable to launch | | `args` | `array[string] \| null` | Arguments passed to the command | | `env` | `object \| null` | Environment variables for the command | ### MultipleMCPConnections | Parameter | Type | Required | Description | | ------------- | ---------------------- | -------- | ----------------------- | | `connections` | `array[MCPConnection]` | Yes | List of MCP connections | ### MCPOAuthConfig Three flavors are supported: the interactive `authorization_code` browser flow (PKCE and dynamic client registration handled for you, so `client_id` is optional), the headless `client_credentials` flow, or supplying a pre-obtained `access_token` so no flow runs at all. | Parameter | Type | Default | Description | | -------------------- | ----------------------- | ---------------------------------- | ------------------------------------------------------------------------------- | | `grant_type` | `string` | `"authorization_code"` | `authorization_code` or `client_credentials` | | `client_id` | `string \| null` | — | Optional for `authorization_code` when the server supports dynamic registration | | `client_secret` | `string \| null` | — | **Required** for `client_credentials` | | `scopes` | `array[string] \| null` | — | Scopes to request, e.g. `["mcp:tools", "offline_access"]` | | `redirect_uri` | `string` | `"http://127.0.0.1:8765/callback"` | Loopback URI that captures the authorization code | | `client_name` | `string` | `"Swarms Agent"` | Client name sent during dynamic registration | | `client_uri` | `string \| null` | — | Client homepage sent during dynamic registration | | `authorization_url` | `string \| null` | discovered | Explicit authorization endpoint | | `token_url` | `string \| null` | discovered | Explicit token endpoint | | `access_token` | `string \| null` | — | Pre-obtained token. When set, no OAuth flow is performed | | `refresh_token` | `string \| null` | — | Pre-obtained refresh token, paired with `access_token` | | `token_storage_path` | `string \| null` | `~/.swarms/mcp_auth/.json` | Where OAuth tokens are cached | | `use_token_cache` | `boolean` | `true` | Persist tokens so the browser flow runs only once | | `open_browser` | `boolean` | `true` | Open the system browser. When `false`, the URL is logged instead | | `callback_timeout` | `integer` | `300` | Seconds to wait for the user to complete the browser flow | Any string field accepts `"env:MY_VAR"` or `"${MY_VAR}"` to read the value from the environment instead of hardcoding a secret. *** ## Response: SwarmCompletion All nine fields are always present in a successful response. | Field | Type | Description | | ------------------ | ----------------- | --------------------------------------------------------------------------------- | | `job_id` | `string \| null` | Unique identifier for this swarm completion | | `status` | `string \| null` | Status of the completion | | `swarm_name` | `string \| null` | The name of the swarm | | `description` | `string \| null` | The description of the swarm | | `swarm_type` | `string \| null` | The architecture that ran | | `output` | `any` | The swarm's output. **Shape varies by `swarm_type`** — a string, array, or object | | `number_of_agents` | `integer \| null` | Number of agents in the swarm | | `execution_time` | `number \| null` | Wall-clock execution time in seconds | | `usage` | `object \| null` | Token counts and cost breakdown | ```json theme={null} { "job_id": "swarm-a1b2c3d4", "status": "success", "swarm_name": "Research Team", "description": "Multi-agent research swarm", "swarm_type": "SequentialWorkflow", "output": [ { "role": "Research Analyst", "content": "Healthcare AI adoption accelerated through 2025, led by imaging and documentation." }, { "role": "Report Writer", "content": "Executive summary: three trends dominate healthcare AI ..." } ], "number_of_agents": 2, "execution_time": 18.42, "usage": { "input_tokens": 420, "output_tokens": 1850, "total_tokens": 2270, "billing_info": { "cost_breakdown": { "agent_cost": 0.02, "input_token_cost": 0.00137, "output_token_cost": 0.01713, "num_agents": 2 }, "total_cost": 0.0385 } } } ``` `output` is untyped in the schema because each architecture returns a different structure — `SequentialWorkflow` returns an ordered conversation, `BatchedGridWorkflow` returns a matrix keyed by agent, `MajorityVoting` returns votes plus a verdict. Branch on `swarm_type` rather than assuming a fixed shape. *** ## Errors | Code | Meaning | | ----- | -------------------------------------------- | | `200` | Completion returned successfully | | `401` | Missing or invalid `x-api-key` | | `402` | Credit balance too low to run the request | | `403` | Model or feature restricted to premium tiers | | `422` | Validation error — see below | | `429` | Rate limit exceeded | | `500` | Internal server error | ### HTTPValidationError A `422` returns a `detail` array with one `ValidationError` per offending field: | Field | Type | Description | | ------- | -------------------------- | --------------------------------------------------- | | `loc` | `array[string \| integer]` | Path to the offending field | | `msg` | `string` | Human-readable message | | `type` | `string` | Error type identifier | | `input` | `any` | The value that failed validation | | `ctx` | `object` | Additional context, such as the violated constraint | ```json theme={null} { "detail": [ { "loc": ["body", "max_loops"], "msg": "Input should be less than or equal to 50", "type": "less_than_equal", "input": 100, "ctx": { "le": 50 } } ] } ``` Common causes: `max_loops` above 50, `agents` longer than 2000, `max_tokens` below 1, `temperature` outside 0–2, a `swarm_type` outside the enum, or `AgentRearrange` without `rearrange_flow`. *** ## Examples ### Basic Swarm Completion ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } swarm_config = { "name": "Research Team", "description": "Research a topic, then write it up", "swarm_type": "SequentialWorkflow", "task": "Analyze the impact of AI on healthcare delivery", "max_loops": 1, "agents": [ { "agent_name": "Research Analyst", "description": "Gathers and structures source material", "system_prompt": "You are a research analyst specializing in healthcare technology.", "model_name": "claude-sonnet-5", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Report Writer", "description": "Turns research into an executive summary", "system_prompt": "You write concise executive summaries for healthcare executives.", "model_name": "claude-sonnet-5", "max_loops": 1, "max_tokens": 4096, "temperature": 0.5, }, ], } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=600, ) response.raise_for_status() result = response.json() print(f"Job {result['job_id']} — {result['number_of_agents']} agents " f"in {result['execution_time']:.1f}s") print(json.dumps(result["output"], indent=2)) ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const swarmConfig = { name: "Research Team", description: "Research a topic, then write it up", swarm_type: "SequentialWorkflow", task: "Analyze the impact of AI on healthcare delivery", max_loops: 1, agents: [ { agent_name: "Research Analyst", description: "Gathers and structures source material", system_prompt: "You are a research analyst specializing in healthcare technology.", model_name: "claude-sonnet-5", max_loops: 1, max_tokens: 4096, temperature: 0.3 }, { agent_name: "Report Writer", description: "Turns research into an executive summary", system_prompt: "You write concise executive summaries for healthcare executives.", model_name: "claude-sonnet-5", max_loops: 1, max_tokens: 4096, temperature: 0.5 } ] }; const response = await fetch(`${BASE_URL}/v1/swarm/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify(swarmConfig) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`); } const result = await response.json(); console.log(`Job ${result.job_id} — ${result.number_of_agents} agents in ${result.execution_time}s`); console.log(JSON.stringify(result.output, null, 2)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/swarm/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Team", "description": "Research a topic, then write it up", "swarm_type": "SequentialWorkflow", "task": "Analyze the impact of AI on healthcare delivery", "max_loops": 1, "agents": [ { "agent_name": "Research Analyst", "description": "Gathers and structures source material", "system_prompt": "You are a research analyst specializing in healthcare technology.", "model_name": "claude-sonnet-5", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3 }, { "agent_name": "Report Writer", "description": "Turns research into an executive summary", "system_prompt": "You write concise executive summaries for healthcare executives.", "model_name": "claude-sonnet-5", "max_loops": 1, "max_tokens": 4096, "temperature": 0.5 } ] }' ``` ### Architecture-Specific Parameters `HierarchicalSwarm` with a tuned director, and `AgentRearrange` with an explicit flow: ```json HierarchicalSwarm theme={null} { "name": "Research Coordination", "swarm_type": "HierarchicalSwarm", "task": "Produce a competitive landscape report on AI coding assistants", "director_model_name": "gpt-5.4", "director_settings": { "temperature": 0.2, "max_tokens": 8000 }, "list_all_agents": true, "agents": [ { "agent_name": "Market Researcher", "role": "worker", "model_name": "claude-sonnet-5" }, { "agent_name": "Pricing Analyst", "role": "worker", "model_name": "claude-sonnet-5" }, { "agent_name": "Technical Reviewer","role": "worker", "model_name": "claude-sonnet-5" } ] } ``` ```json AgentRearrange theme={null} { "name": "Content Pipeline", "swarm_type": "AgentRearrange", "rearrange_flow": "Researcher -> Writer, Editor", "task": "Draft a technical blog post on vector databases", "agents": [ { "agent_name": "Researcher", "model_name": "claude-sonnet-5" }, { "agent_name": "Writer", "model_name": "claude-sonnet-5" }, { "agent_name": "Editor", "model_name": "claude-sonnet-5" } ] } ``` ```json HeavySwarm theme={null} { "name": "Market Analysis", "swarm_type": "HeavySwarm", "task": "Analyze the renewable energy sector outlook", "agents": [], "heavy_swarm_variant": "heavy", "heavy_swarm_max_loops": 2, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514" } ``` `HeavySwarm` builds its own agents internally — pass `"agents": []`. See [HeavySwarm](/docs/documentation/multi-agent/heavy_swarm). ### Streaming Set `stream: true` to receive output as it is produced rather than waiting for the full run. ```python theme={null} response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={**swarm_config, "stream": True}, stream=True, timeout=600, ) for line in response.iter_lines(): if line: print(line.decode("utf-8")) ``` See [Streaming](/docs/examples/examples/streaming) and [Swarm Streaming](/docs/examples/examples/swarm-streaming) for the event shapes. *** ## Related Resources Conceptual introduction to swarms Pick the right topology for your task Run up to 50 swarms in one request The single-agent endpoint DAG orchestration on its own endpoint How swarm runs are billed # Official Client Libraries Source: https://docs.swarms.ai/docs/documentation/resources/client-libraries Discover official SDKs and client libraries for the Swarms API in multiple programming languages. The Swarms API provides official client libraries across multiple programming languages, enabling developers to integrate powerful multi-agent AI capabilities into their applications with ease. Our clients are designed for production use, featuring robust error handling, comprehensive documentation, and seamless integration with existing codebases. Whether you're building enterprise applications, research prototypes, or innovative AI products, our client libraries provide the tools you need to harness the full power of the Swarms platform. ### Available Clients | Language | Status | Repository | Documentation | Description | | ---------------------- | ------------------ | ----------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | **Python** | ✅ **Available** | [swarms-client](https://github.com/The-Swarm-Corporation/swarms-client) | [Python Client Guide](/docs/documentation/clients/python-client) | Production-grade Python client with comprehensive error handling, retry logic, and extensive examples | | **TypeScript/Node.js** | ✅ **Available** | [swarms-ts](https://github.com/The-Swarm-Corporation/swarms-ts) | 📚 *Coming Soon* | Modern TypeScript client with full type safety, Promise-based API, and Node.js compatibility | | **Go** | ✅ **Available** | [swarms-client-go](https://github.com/The-Swarm-Corporation/swarms-client-go) | 📚 *Coming Soon* | High-performance Go client optimized for concurrent operations and microservices | | **Java** | ✅ **Available** | [swarms-java](https://github.com/The-Swarm-Corporation/swarms-java) | 📚 *Coming Soon* | Enterprise Java client with Spring Boot integration and comprehensive SDK features | | **Kotlin** | 🚧 **Coming Soon** | *In Development* | 📚 *Coming Soon* | Modern Kotlin client with coroutines support and Android compatibility | | **Ruby** | 🚧 **Coming Soon** | *In Development* | 📚 *Coming Soon* | Elegant Ruby client with Rails integration and gem packaging | | **Rust** | 🚧 **Coming Soon** | *In Development* | 📚 *Coming Soon* | Ultra-fast Rust client with memory safety and zero-cost abstractions | | **C#/.NET** | 🚧 **Coming Soon** | *In Development* | 📚 *Coming Soon* | .NET client with async/await support and NuGet packaging | ### Client Features *Ready to build the future with AI agents? Start with any of our client libraries and join our growing community of developers building the next generation of intelligent applications.* # Community Source: https://docs.swarms.ai/docs/documentation/resources/community Connect with the Swarms community of agent engineers and researchers Join our community of agent engineers and researchers for technical support, cutting-edge updates, and exclusive access to world-class agent engineering insights! | Platform | Description | Link | | --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | 💬 Discord | Live chat and community support | [Join Discord](https://discord.gg/EamjgSaEQf) | | 🐦 X (Twitter) | Latest news and announcements | [@swarms\_corp](https://twitter.com/swarms_corp) | | 📚 Documentation | Official documentation and guides | [docs.swarms.ai](https://docs.swarms.ai) | | 📝 Blog | Latest updates and technical articles | [Medium](https://medium.com/@kyeg) | | 👥 LinkedIn | Professional network and updates | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | | 📺 YouTube | Tutorials and demos | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | | 🎫 Events | Join our community events | [Sign up here](https://luma.com/swarms_calendar) | | 🚀 Onboarding Session | Get onboarded with Kye Gomez, creator and lead maintainer of Swarms | [Book Session](https://cal.com/swarms/swarms-onboarding-session) | ## Get Started Today Join the swarms community now. Here's how to get started: 1. **Join Discord** - Connect with other developers in real-time 2. **Follow on Social Media** - Stay updated with the latest news 3. **Book an Onboarding Session** - Get personalized guidance 4. **Share Your Projects** - Show the community what you're building 5. **Ask Questions** - Don't hesitate to reach out for help We're excited to have you as part of our growing community of thousands of agent engineers and researchers! # Contributors Source: https://docs.swarms.ai/docs/documentation/resources/contributors Help us maintain and improve the Swarms API documentation, examples, and client libraries We're building the future of agentic civilizations, and we need your help! The Swarms API documentation is a community-driven project that thrives on contributions from developers like you. Help keep our docs accurate, clear, and up-to-date Create practical examples and tutorials for developers Maintain and improve our Python and TypeScript SDKs Help other developers in our Discord and GitHub discussions ## How to Contribute ### Getting Started 1. **Fork the repository**: [swarms-api-docs](https://github.com/The-Swarm-Corporation/swarms-api-docs) 2. **Join our Discord**: [Swarms Discord](https://discord.gg/EamjgSaEQf) 3. **Check existing issues**: Look for issues labeled `good first issue` or `help wanted` 4. **Set up development environment**: Follow our [development setup guide](#development-setup) ### Development Setup ```bash theme={null} npm install -g @mintlify/cli ``` ```bash theme={null} git clone https://github.com/The-Swarm-Corporation/swarms-api-docs.git cd swarms-api-docs ``` ```bash theme={null} mint dev ``` Navigate to `http://localhost:3000` to see your changes ## Contribution Areas ### Documentation Maintenance Help us keep the documentation accurate and comprehensive: **What we need help with:** * Fixing typos and grammatical errors * Updating outdated information * Improving clarity and readability * Adding missing explanations * Translating content to other languages **How to contribute:** 1. Look for issues labeled `documentation` 2. Create a pull request with your changes 3. Ensure all changes are tested locally with `mint dev` **Files to focus on:** * `/getting-started/` - Setup and quickstart guides * `/capabilities/` - Feature documentation * `/multi-agent/` - Multi-agent system guides * `/clients/` - Client library documentation ### Example Development Create practical examples that help developers understand the Swarms API: **What we need help with:** * Real-world use case examples * Industry-specific implementations * Advanced multi-agent workflows * Integration examples with popular frameworks * Performance optimization examples **Example categories we're looking for:** * **Healthcare**: Patient data analysis, medical research * **Finance**: Risk assessment, fraud detection * **E-commerce**: Product recommendations, customer service * **Education**: Personalized learning, content generation * **Legal**: Document analysis, case research **How to contribute:** 1. Create examples in the `/examples/` directory 2. Include both `.mdx` documentation and `.py` code files 3. Add comprehensive comments and explanations 4. Test examples with real API calls **Example structure:** ``` examples/ ├── your-example/ │ ├── your-example.mdx │ ├── your-example.py │ └── requirements.txt ``` ### Client Libraries Help maintain and improve our official client libraries: **Python SDK**: [swarms-client](https://github.com/The-Swarm-Corporation/swarms-client) * Add new features and endpoints * Improve error handling * Add type hints and documentation * Create comprehensive tests * Optimize performance **TypeScript SDK**: [swarms-ts](https://github.com/The-Swarm-Corporation/swarms-ts) * Implement missing features * Add TypeScript definitions * Create React/Node.js examples * Improve developer experience **How to contribute:** 1. Fork the respective repository 2. Check existing issues and feature requests 3. Follow the project's contribution guidelines 4. Write tests for new features 5. Update documentation ### Community Support Help other developers succeed with the Swarms API: **Ways to help:** * Answer questions in [Discord](https://discord.gg/EamjgSaEQf) * Respond to GitHub issues and discussions * Create tutorial videos or blog posts * Share your projects and use cases * Provide feedback on new features ## Contribution Guidelines ### Code Style * Follow existing code patterns and conventions * Use clear, descriptive variable and function names * Add comments for complex logic * Ensure all code is properly formatted ### Documentation Style * Use clear, concise language * Include code examples where helpful * Follow the existing documentation structure * Test all code examples before submitting ### Pull Request Process 1. **Create a feature branch**: `git checkout -b feature/your-feature-name` 2. **Make your changes**: Follow the contribution guidelines 3. **Test locally**: Run `mint dev` to ensure everything works 4. **Commit changes**: Use clear, descriptive commit messages 5. **Create pull request**: Include a detailed description of your changes 6. **Respond to feedback**: Be open to suggestions and improvements ### Commit Message Format ``` type(scope): brief description Detailed explanation of changes (if needed) Fixes #issue-number ``` **Types:** * `docs`: Documentation changes * `feat`: New features * `fix`: Bug fixes * `example`: New examples * `refactor`: Code refactoring * `test`: Adding or updating tests ## Recognition We value all contributions to the Swarms ecosystem: **Contributor Benefits:** * Recognition in our contributor hall of fame * Early access to new features and APIs * Direct communication with the Swarms team * Potential opportunities for collaboration * Swarms merchandise and swag **Contributor Levels:** * **Community Member**: First contribution * **Active Contributor**: 5+ contributions * **Core Contributor**: 20+ contributions or significant impact * **Maintainer**: Long-term commitment and leadership ## Getting Help **Need help getting started?** * Join our [Discord community](https://discord.gg/EamjgSaEQf) * Check out our [GitHub discussions](https://github.com/The-Swarm-Corporation/swarms-api-docs/discussions) * Schedule [technical support](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) **Have questions about contributing?** * Open a [GitHub issue](https://github.com/The-Swarm-Corporation/swarms-api-docs/issues) * Tag maintainers in Discord * Reach out to us on [Twitter](https://twitter.com/swarms_corp) ## Current Contributors We're grateful to all our contributors who help make the Swarms API documentation better every day. Want to see your name here? Start contributing today! Every contribution, no matter how small, makes a difference. *** **Ready to contribute?** [Fork the repository](https://github.com/The-Swarm-Corporation/swarms-api-docs) and join our community today! # Global Availability Source: https://docs.swarms.ai/docs/documentation/resources/global-availability Swarms platform is now globally available across four regions for reduced latency and improved reliability. To serve our growing international user base, the Swarms platform is now globally available across four regions: * **US West** * **US East** * **Europe** * **Asia** This deployment significantly reduces latency for global customers, offering faster response times and improved reliability for enterprise-scale workloads. ### Automatic Routing When you make a request to the Swarms API, you are automatically routed to the closest server based on your geographic location. This intelligent routing ensures: * **Optimal Performance**: Your requests are handled by the nearest data center * **Minimal Latency**: Network distance is minimized for faster response times * **Seamless Experience**: No configuration needed - routing happens automatically * **Load Balancing**: Traffic is distributed efficiently across regions ### Benefits * **Reduced Latency**: Connect to the nearest region for optimal performance * **Improved Reliability**: Multiple regions ensure high availability and redundancy * **Enterprise-Scale**: Built to handle enterprise workloads with global distribution * **Faster Response Times**: Geographic proximity to users ensures quicker API responses # Premium Endpoints Source: https://docs.swarms.ai/docs/documentation/resources/premium-endpoints Endpoints available exclusively to Pro and Ultra plan members Access to these endpoints is restricted to Pro and Ultra plans. To upgrade, see Pricing. ## Premium Endpoints | Endpoint | Method | Description | | --------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `/v1/graph-workflow/completions` | POST | Execute graph workflows with directed agent nodes and edges. Enables complex multi-agent collaboration with parallel execution, automatic compilation, and comprehensive workflow orchestration. | | `/v1/agent/batch/completions` | POST | Process multiple agent tasks in parallel batches with high-throughput batch processing capabilities. Ideal for large-scale document analysis, data processing, and enterprise-scale operations. | | `/v1/swarm/batch/completions` | POST | Execute batch swarm completions with concurrent multi-agent execution for complex collaborative workflows at scale. | | `/v1/reasoning-agent/completions` | POST | Execute advanced reasoning agent tasks using specialized reasoning architectures like self-consistency, majority voting, and iterative refinement for improved answer quality and reliability. | | `/v1/batched-grid-workflow/completions` | POST | Execute multiple tasks across multiple agents in a grid pattern with parallel batch processing. Creates comprehensive task-agent matrices for comparative analysis and multi-perspective evaluation. | ### Why These Endpoints Require Premium Access These endpoints are resource-intensive operations that provide: * **High-throughput batch processing** - Process hundreds of tasks concurrently * **Concurrent multi-agent execution** - Run multiple specialized agents simultaneously * **Advanced reasoning capabilities** - Utilize sophisticated reasoning architectures for complex problem-solving * **Enterprise-scale workflow orchestration** - Coordinate large-scale, multi-step agent workflows Premium tier restrictions ensure sustainable infrastructure costs while maintaining quality service for enterprise customers. ### Error Response for Free Tier Users Free tier users attempting to access these endpoints will receive a **403 Forbidden** error with upgrade instructions: ```json theme={null} { "error": { "type": "premium_access_required", "message": "Premium subscription required", "detail": "Access to Batch Agent Completions requires a premium subscription. This feature allows you to process multiple agent tasks concurrently in a single request. Your current account is on the free tier, which does not include access to premium features. To unlock this and other premium capabilities, please upgrade your account at https://swarms.world/platform/account. Premium subscriptions provide access to high-throughput batch processing, concurrent execution, advanced reasoning agents, and enterprise-scale workflow orchestration.", "status_code": 403, "upgrade_url": "https://swarms.world/platform/account", "documentation": "https://docs.swarms.ai/docs/documentation/resources/pricing" } } ``` The `detail` message is tailored per endpoint (naming the specific feature you tried to access). ### Notes * These endpoints may have different rate limits aligned with premium tiers. * Ensure your API key is associated with a Pro, Ultra, or Premium subscription. * Premium endpoints are also billable: your account's total credit balance must be above \$1.00, or the request is rejected with a **402 Payment Required** error before any work runs. Check your balance with `GET /v1/account/credits`. * Beyond these five endpoints, certain models (e.g. GPT-5.6, Claude Opus 5, Gemini 3.1 Pro) are also gated to premium subscribers on regular endpoints like `/v1/agent/completions` and `/v1/swarm/completions` — see [Pricing](/docs/documentation/resources/pricing) for the current list. * For endpoint schemas and examples, see related documentation pages. # Pricing Source: https://docs.swarms.ai/docs/documentation/resources/pricing This page details the pricing structure and how credits are deducted for various API operations. This page details the pricing structure and how credits are deducted for various API operations. To upgrade your plan, visit the Account Dashboard, open the Billing tab, and select your tier. ## API Subscriptions Flexible subscription plans that scale with your needs. Choose a plan for higher limits and features; usage is billed per operation. ### Plans at a glance | Plan | Monthly price | Discount % | Annual price | Premium Endpoints | SOC 2 | Priority routing | Support | Best for | Key features | | ----- | ------------: | ---------- | ------------: | ----------------- | :---: | :--------------: | --------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | | Free | \$0 | N/A | \$0/year | No | No | No | Community | Getting started | Basic API, pay‑per‑use, community support, Marketplace access | | Pro | \$19.99 | 15% | \$203.90/year | Yes | No | No | Priority | Professionals | Global availability, multi‑agent architectures, accelerated hardware, API telemetry, priority support, Pro models, Premium Endpoints access | | Ultra | \$100 | 15% | \$1,020/year | Yes | Yes | Yes | Priority | Teams & production | Everything in Pro, premium models, higher limits, SOC 2, enhanced security, priority region/zone routing, full Premium Endpoints | Prices shown are subscription fees; API usage is billed per operation (see Usage-based pricing below). ### Update your plan in 3 steps 1. Go to the Account Dashboard. 2. Open the Billing tab and scroll down to the Plans section. 3. Select your desired plan. You’ll be redirected to Stripe to complete payment. ### Free Get started with AI. No monthly fees — pay only for usage. * Sign-up bonus credits * Basic API access * Pay-per-use pricing * Community support * Standard processing speed * Access to the Marketplace * **Note**: Premium endpoints (batch processing, reasoning agents, advanced workflows) are not available on the free tier ### Pro Most popular. Perfect for professionals who need more power and features. * \$19.99/month (save 15% with annual billing) * Global availability * Exclusive multi-agent architectures * Accelerated hardware * API telemetry platform * Priority support * Access to Pro models * **Access to Premium Endpoints**: Unlock batch processing, reasoning agents, and advanced workflows * `/v1/agent/batch/completions` - High-throughput batch agent processing * `/v1/swarm/batch/completions` - Batch swarm completions * `/v1/reasoning-agent/completions` - Advanced reasoning capabilities * `/v1/batched-grid-workflow/completions` - Grid workflow execution * Plus graph workflows * See full list: Premium Endpoints ### Ultra Best for growing teams and production workloads that need higher limits and security. * \$100/month (save 15% with annual billing) * Everything in Pro, plus: * Premium models * More agents per request * More completions * Increased rate limits * SOC 2 compliance * Enhanced security features * View previous agent configurations * Priority region/zone routing * Full access to Premium Endpoints ### Premium-Only Models Free tier accounts are blocked from requesting the following models on any endpoint (including `/v1/agent/completions` and `/v1/swarm/completions`), regardless of available credits. Any active Pro or Ultra subscription unlocks all of them — there is no separate model tier between Pro and Ultra: * `gpt-5.6-sol` * `gpt-5.6-terra` * `gpt-5.6-luna` * `gpt-5.6` * `claude-fable-5` * `claude-opus-5` * `claude-opus-4-8` * `gemini-3.1-pro` * `gemini-3.1-deep-think` * `xai/grok-4.5` * `xai/grok-4.5-latest` * Any `groq/*` model Requesting one of these models on the free tier returns a 403 error with suggested free-tier alternatives. ### Enterprise Critical support, compliance, and control for large-scale enterprises. * Contact sales for custom pricing * Dedicated 24/7 support * Custom solutions engineering * Onsite training and onboarding * Custom agent development * No rate limits * Access to experimental features ## Usage-based pricing Pay only for what you use with transparent, per-operation pricing. All API endpoints use a unified pricing structure for token costs. ### Pricing Table | Item | Price | Unit | Notes | | ----------------------- | -------------- | -------------- | ------------------------------------ | | **Input Tokens** | \$6.50 | per 1M tokens | Unified pricing across all endpoints | | **Output Tokens** | \$18.50 | per 1M tokens | Unified pricing across all endpoints | | **Agent Cost** | \$0.01 | per agent | For swarms and workflows | | **Image Processing** | \$0.25 | per image | Charged when image provided | | **MCP Call** | \$0.10 | per call | Charged when MCP URL provided | | **Exa Search Tool** | \$0.04 | per search | Charged per search execution | | **Web Scraper Tool** | \$0.15 | per scrape | Charged per scrape execution | | **Night-time Discount** | 50% off tokens | 8 PM - 6 AM PT | Swarm Completions only | ### Unified Pricing All API endpoints use the same token pricing: * **Input Tokens**: \$6.50 per 1 million tokens * **Output Tokens**: \$18.50 per 1 million tokens This applies to: | Endpoint | Notes | | --------------------- | ------------------ | | Swarm Completions | Agent cost applies | | Agent Completions | | | Graph Workflow | Agent cost applies | | Batched Grid Workflow | Agent cost applies | ### Discounts **Night Time Discount**: Swarm completions receive a 50% discount on token costs during 8 PM - 6 AM Pacific Time. Agent costs remain the same. ### Retrieving Current Costs You can retrieve the current pricing using the `/v1/usage/costs` endpoint: ```bash theme={null} GET /v1/usage/costs ``` **Example Response:** ```json theme={null} { "usage_pricing": { "swarm_completions_agent_cost": 0.01, "swarm_completions_input_cost_per_1m": 6.5, "swarm_completions_output_cost_per_1m": 18.5, "agent_completions_input_cost_per_1m": 6.5, "agent_completions_output_cost_per_1m": 18.5, "agent_completions_img_cost": 0.25, "agent_completions_mcp_cost": 0.1, "search_cost": 0.04, "scrape_cost": 0.15, "night_time_discount": 0.5 }, "timestamp": "2026-03-29T18:30:00+00:00" } ``` ### Important Notes | Important Note | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Minimum Balance | Billable completion endpoints require a total credit balance above \$1.00, checked before the request runs. Requests below this are rejected with a **402 Payment Required** error before any work is done. | | Credits Deduction | Credits are deducted automatically after each request completes. | | Credits Usage Order | Free credits are used first, followed by regular credits. | | Token Counting | Token counts are calculated using model-specific tokenizers. | | Pricing Updates | Pricing may be updated periodically. Check `/v1/usage/costs` for current pricing. | # Priority Processing Source: https://docs.swarms.ai/docs/documentation/resources/priority-processing Learn how the Swarms API handles request priority for premium subscribers during high demand periods The Swarms API uses a fair and efficient system to handle requests, especially during periods of high demand. Premium subscribers (such as those on Pro, Ultra, or higher tiers) receive priority processing for their requests. This helps ensure faster and more reliable performance when the system is busy. Free tier users may experience slightly longer wait times under heavy load, but the system is designed to serve everyone reliably. ## How Priority Works ### Premium Priority Requests from premium accounts are processed ahead of free tier requests when resources are limited. This includes benefits like access to closer servers (availability zones) for reduced latency. ### Fairness for All The system prevents any single tier from overwhelming resources, ensuring free users still get service without excessive delays. ### No Changes Needed This happens automatically based on your API key and subscription no extra code or settings required on your end. ## Benefits for Premium Users * Quicker response times during peak usage * Better overall performance and consistency * Additional perks like higher rate limits and priority support To upgrade to a premium plan and unlock priority processing, visit your Account Dashboard or check the Pricing page. If you have questions, feel free to reach out to support! # Rate Limit Headers Source: https://docs.swarms.ai/docs/documentation/resources/rate-limit-headers Rate-limited API responses include X-RateLimit-* headers so you can track your usage and remaining quota in real time without making a separate API call. Swarms API responses include rate limit headers whenever the rate limiter runs on the request. These headers let you monitor your usage programmatically — build retry logic, display quota dashboards, or throttle requests before hitting limits. Rate limit headers are present on every response where the rate limiter ran — including 429 rate-limit rejections and `/v1/rate/limits` itself. Errors returned before rate limiting runs (such as 402 insufficient-credit or 403 premium-required rejections from the authentication layer) do not carry these headers. *** ## Headers Rate-limited responses include these headers: | Header | Type | Description | | ------------------------------ | -------------- | ----------------------------------------------------------------------- | | `X-RateLimit-Limit-Minute` | integer | Maximum requests allowed per minute for your tier | | `X-RateLimit-Remaining-Minute` | integer | Requests remaining in the current minute window | | `X-RateLimit-Limit-Day` | integer | Maximum requests allowed per day for your tier | | `X-RateLimit-Remaining-Day` | integer | Requests remaining in the current day window | | `X-RateLimit-Reset` | unix timestamp | When the current minute window resets (seconds since epoch) | | `X-RateLimit-Tier` | string | Your current tier: `free` or `premium` | | `Retry-After` | integer | Seconds until the rate limit resets. **Only present on 429 responses.** | *** ## Example Response Headers ```http theme={null} HTTP/1.1 200 OK Content-Type: application/json X-RateLimit-Limit-Minute: 100 X-RateLimit-Remaining-Minute: 94 X-RateLimit-Limit-Day: 1200 X-RateLimit-Remaining-Day: 1047 X-RateLimit-Reset: 1713700800 X-RateLimit-Tier: free ``` *** ## Example 429 Response When you exceed a rate limit, the response includes a `Retry-After` header: ```http theme={null} HTTP/1.1 429 Too Many Requests Content-Type: application/json X-RateLimit-Limit-Minute: 100 X-RateLimit-Remaining-Minute: 0 X-RateLimit-Limit-Day: 1200 X-RateLimit-Remaining-Day: 1100 X-RateLimit-Reset: 1713700860 X-RateLimit-Tier: free Retry-After: 42 ``` ```json theme={null} { "detail": "Rate limit exceeded for minute window(s). Upgrade to Premium for increased limits (2,000/min, 10,000/hour, 100,000/day) at https://swarms.world/platform/account for just $99/month. See https://docs.swarms.ai/docs/documentation/resources/ratelimits for current limits and how they are counted." } ``` *** ## Limits by Tier | | Free | Premium | | -------------------- | ------- | --------- | | **Per minute** | 100 | 2,000 | | **Per hour** | 350 | 10,000 | | **Per day** | 1,200 | 100,000 | | **Tokens per agent** | 200,000 | 2,000,000 | *** ## Code Examples ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json={ "agent_config": { "agent_name": "test", "model_name": "gpt-4o-mini", "system_prompt": "You are helpful.", "max_loops": 1, }, "task": "Say hello.", }, ) # Read rate limit headers remaining = int(response.headers["X-RateLimit-Remaining-Minute"]) limit = int(response.headers["X-RateLimit-Limit-Minute"]) tier = response.headers["X-RateLimit-Tier"] print(f"Tier: {tier} | {remaining}/{limit} requests remaining this minute") ``` ```typescript theme={null} import "dotenv/config"; const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; if (!API_KEY) { throw new Error("SWARMS_API_KEY is not set"); } const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ agent_config: { agent_name: "test", model_name: "gpt-4o-mini", system_prompt: "You are helpful.", max_loops: 1, }, task: "Say hello.", }), }); // Read rate limit headers const remaining = parseInt(response.headers.get("X-RateLimit-Remaining-Minute") ?? "0"); const limit = parseInt(response.headers.get("X-RateLimit-Limit-Minute") ?? "0"); const tier = response.headers.get("X-RateLimit-Tier"); console.log(`Tier: ${tier} | ${remaining}/${limit} requests remaining this minute`); ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY") .expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let response = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", &api_key) .header("Content-Type", "application/json") .body(r#"{ "agent_config": { "agent_name": "test", "model_name": "gpt-4o-mini", "system_prompt": "You are helpful.", "max_loops": 1 }, "task": "Say hello." }"#) .send()?; // Read rate limit headers let remaining = response.headers() .get("X-RateLimit-Remaining-Minute") .and_then(|v| v.to_str().ok()) .unwrap_or("0"); let limit = response.headers() .get("X-RateLimit-Limit-Minute") .and_then(|v| v.to_str().ok()) .unwrap_or("0"); let tier = response.headers() .get("X-RateLimit-Tier") .and_then(|v| v.to_str().ok()) .unwrap_or("unknown"); println!("Tier: {} | {}/{} requests remaining this minute", tier, remaining, limit); Ok(()) } ``` ```go theme={null} package main import ( "fmt" "log" "net/http" "os" "strings" ) func main() { apiKey := os.Getenv("SWARMS_API_KEY") if apiKey == "" { log.Fatal("SWARMS_API_KEY environment variable is required") } body := strings.NewReader(`{ "agent_config": { "agent_name": "test", "model_name": "gpt-4o-mini", "system_prompt": "You are helpful.", "max_loops": 1 }, "task": "Say hello." }`) req, err := http.NewRequest("POST", "https://api.swarms.world/v1/agent/completions", body) if err != nil { log.Fatal(err) } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() // Read rate limit headers remaining := resp.Header.Get("X-RateLimit-Remaining-Minute") limit := resp.Header.Get("X-RateLimit-Limit-Minute") tier := resp.Header.Get("X-RateLimit-Tier") fmt.Printf("Tier: %s | %s/%s requests remaining this minute\n", tier, remaining, limit) } ``` ```bash theme={null} # The -i flag prints response headers curl -i -X POST https://api.swarms.world/v1/agent/completions \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "test", "model_name": "gpt-4o-mini", "system_prompt": "You are helpful.", "max_loops": 1 }, "task": "Say hello." }' ``` *** ## Retry Logic Use the `Retry-After` header to implement automatic retry on 429 responses: ```python theme={null} import time import requests def call_with_retry(url, headers, payload, max_retries=3): for attempt in range(max_retries): response = requests.post(url, headers=headers, json=payload) if response.status_code == 429: retry_after = int(response.headers.get("Retry-After", 60)) print(f"Rate limited. Retrying in {retry_after}s...") time.sleep(retry_after) continue return response raise Exception("Max retries exceeded") ``` ```typescript theme={null} async function callWithRetry( url: string, headers: Record, payload: object, maxRetries = 3 ): Promise { for (let attempt = 0; attempt < maxRetries; attempt++) { const response = await fetch(url, { method: "POST", headers, body: JSON.stringify(payload), }); if (response.status === 429) { const retryAfter = parseInt(response.headers.get("Retry-After") ?? "60"); console.log(`Rate limited. Retrying in ${retryAfter}s...`); await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000)); continue; } return response; } throw new Error("Max retries exceeded"); } ``` ```rust theme={null} use reqwest::blocking::{Client, Response}; use std::thread; use std::time::Duration; fn call_with_retry( client: &Client, url: &str, api_key: &str, body: &str, max_retries: u32, ) -> Result> { for _ in 0..max_retries { let response = client .post(url) .header("x-api-key", api_key) .header("Content-Type", "application/json") .body(body.to_string()) .send()?; if response.status().as_u16() == 429 { let retry_after: u64 = response.headers() .get("Retry-After") .and_then(|v| v.to_str().ok()) .and_then(|v| v.parse().ok()) .unwrap_or(60); println!("Rate limited. Retrying in {}s...", retry_after); thread::sleep(Duration::from_secs(retry_after)); continue; } return Ok(response); } Err("Max retries exceeded".into()) } ``` ```go theme={null} package main import ( "fmt" "net/http" "strconv" "strings" "time" ) func callWithRetry(url, apiKey, body string, maxRetries int) (*http.Response, error) { for attempt := 0; attempt < maxRetries; attempt++ { req, err := http.NewRequest("POST", url, strings.NewReader(body)) if err != nil { return nil, err } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } if resp.StatusCode == 429 { retryAfter, _ := strconv.Atoi(resp.Header.Get("Retry-After")) if retryAfter == 0 { retryAfter = 60 } fmt.Printf("Rate limited. Retrying in %ds...\n", retryAfter) resp.Body.Close() time.Sleep(time.Duration(retryAfter) * time.Second) continue } return resp, nil } return nil, fmt.Errorf("max retries exceeded") } ``` *** ## Best Practices 1. **Check `Remaining-Minute` before sending requests** — if it's low, slow down or queue requests. 2. **Use `Retry-After` on 429s** — don't guess the wait time, the header tells you exactly how long. 3. **Log your tier** — use `X-RateLimit-Tier` to confirm your account is on the expected plan. 4. **Build dashboards** — track `Remaining-Day` over time to understand your usage patterns and plan upgrades. *** ## Related * [Rate Limits](/docs/documentation/resources/ratelimits) — full rate limit tiers, windows, and how limiting works * [Pricing Details](/docs/documentation/resources/pricing) — per-operation costs * [Premium Endpoints](/docs/documentation/resources/premium-endpoints) — endpoints available on premium plans * [Rate Limits API Example](/docs/examples/api_examples/rate_limits) — check rate limit status via the API # Rate Limits Source: https://docs.swarms.ai/docs/documentation/resources/ratelimits The Swarms API implements a comprehensive rate limiting system that tracks API requests across multiple time windows and enforces various limits to ensure fair usage and system stability. ## Rate Limits Summary | Rate Limit Type | Free Tier | Premium Tier | Time Window | Description | | ----------------------- | --------- | ------------ | ----------- | --------------------------------------------------------------------- | | **Requests per Minute** | 100 | 2,000 | 1 minute | Maximum completed billable requests per minute | | **Requests per Hour** | 350 | 10,000 | 1 hour | Maximum completed billable requests per hour | | **Requests per Day** | 1,200 | 100,000 | 24 hours | Maximum completed billable requests per day | | **Tokens per Agent** | 200,000 | 2,000,000 | Per request | Maximum tokens per agent | | **Prompt Length** | 200,000 | 2,000,000 | Per request | Maximum input tokens per request (same limit as tokens per agent) | | **Batch Size** | 50 | 50 | Per request | Maximum tasks per agent batch request (`/v1/agent/batch/completions`) | | **IP-based Fallback** | 100 | 100 | 60 seconds | For requests without API keys | ## Detailed Rate Limit Explanations ### 1. **Request Rate Limits** These limits control how many API calls you can make within specific time windows. #### **Per-Minute Limit** | Tier | Requests per Minute | Reset Interval | Enforced On | | ------- | ------------------- | ---------------------- | ---------------------------------------------------------- | | Free | 100 | Every minute (sliding) | All API endpoints (only completed billable requests count) | | Premium | 2,000 | Every minute (sliding) | All API endpoints (only completed billable requests count) | #### **Per-Hour Limit** * **Free Tier**: 350 requests per hour * **Premium Tier**: 10,000 requests per hour * **Reset**: Every hour (sliding window) * **Enforced on**: All API endpoints (only completed billable requests count) #### **Per-Day Limit** * **Free Tier**: 1,200 requests per day (50 × 24) * **Premium Tier**: 100,000 requests per day * **Reset**: Every 24 hours (sliding window) * **Enforced on**: All API endpoints (only completed billable requests count) ### 2. **Token Limits** These limits control the amount of text processing allowed per request. #### **Tokens per Agent** * **Free Tier**: 200,000 tokens per agent * **Premium Tier**: 2,000,000 tokens per agent * **Applies to**: Individual agent configurations * **Includes**: System prompts, task descriptions, and agent names #### **Prompt Length Limit** * **Free Tier**: 200,000 tokens maximum * **Premium Tier**: 2,000,000 tokens maximum * **Applies to**: Combined input text (task + history + system prompts) — this uses the same per-tier `tokens_per_agent` limit as above * **Error**: Returns 400 error if exceeded * **Message**: "Prompt is too long. Please provide a prompt that is less than 200,000 tokens." (limit reflects your tier) ### 3. **Batch Processing Limits** These limits control concurrent processing capabilities. **Premium Access Required**: Batch endpoints (`/v1/agent/batch/completions`, `/v1/swarm/batch/completions`) are available only on Pro, Ultra, and Premium plans. See [Premium Endpoints](/docs/documentation/resources/premium-endpoints). #### **Batch Size Limit** * **`/v1/agent/batch/completions`**: 50 agent tasks maximum per batch. This cap is enforced at the request-validation layer, so exceeding it returns a 422 error before your request reaches application logic. * **`/v1/swarm/batch/completions`**: 50 swarm specs maximum per batch. This cap is enforced at the request-validation layer, so exceeding it returns a 422 error before your request reaches application logic. ## How Rate Limiting Works ### Database-Based Tracking The system uses a database-based approach for API key requests: 1. **Request Logging**: Completed billable work is logged to the `swarms_api_logs` table with the `completion` category 2. **Time Window Queries**: The system counts `completion` rows in the last minute, hour, and day. Telemetry and input rows are deliberately excluded, so GET endpoints and work that never completed do not increment your counters — each completed swarm, agent, or workflow run counts exactly once 3. **Limit Comparison**: Current counts are compared against configured limits 4. **Request Blocking**: Requests are blocked if any limit is exceeded — the limits are enforced on all endpoints, even though only completed billable requests count toward them ### Sliding Windows Rate limits use sliding windows rather than fixed windows: * **Minute**: Counts requests in the last 60 seconds * **Hour**: Counts requests in the last 60 minutes * **Day**: Counts requests in the last 24 hours This provides more accurate rate limiting compared to fixed time windows. ## Checking Your Rate Limits ### API Endpoint Use the `/v1/rate/limits` endpoint to check your current usage: ```bash theme={null} curl -H "x-api-key: your-api-key" \ https://api.swarms.world/v1/rate/limits ``` ### Response Format ```json theme={null} { "success": true, "rate_limits": { "minute": { "count": 5, "limit": 100, "exceeded": false, "remaining": 95, "reset_time": "2024-01-15T10:30:00Z" }, "hour": { "count": 25, "limit": 350, "exceeded": false, "remaining": 325, "reset_time": "2024-01-15T11:00:00Z" }, "day": { "count": 150, "limit": 1200, "exceeded": false, "remaining": 1050, "reset_time": "2024-01-16T10:00:00Z" } }, "limits": { "maximum_requests_per_minute": 100, "maximum_requests_per_hour": 350, "maximum_requests_per_day": 1200, "tokens_per_agent": 200000 }, "tier": "free", "timestamp": "2024-01-15T10:29:30Z" } ``` ### Rate Limit Headers Every rate-limited response also includes `X-RateLimit-*` headers (per-minute and per-day limits, remaining counts, reset time, and your tier), so you can track usage without an extra API call — see [Rate Limit Headers](/docs/documentation/resources/rate-limit-headers). ## Handling Rate Limit Errors ### Error Response When rate limits are exceeded, you'll receive a 429 status code: ```json theme={null} { "detail": "Rate limit exceeded for minute window(s). Upgrade to Premium for increased limits (2,000/min, 10,000/hour, 100,000/day) at https://swarms.world/platform/account for just $99/month. See https://docs.swarms.ai/docs/documentation/resources/ratelimits for current limits and how they are counted." } ``` ### Best Practices 1. **Monitor Usage**: Regularly check your rate limits using the `/v1/rate/limits` endpoint 2. **Implement Retry Logic**: Use exponential backoff when hitting rate limits 3. **Optimize Requests**: Combine multiple operations into single requests when possible 4. **Upgrade When Needed**: Consider upgrading to Premium for higher limits ## Premium Tier Benefits Upgrade to Premium for significantly higher limits: * **20x more requests per minute** (2,000 vs 100) * **\~29x more requests per hour** (10,000 vs 350) * **83x more requests per day** (100,000 vs 1,200) * **10x more tokens per agent** (2M vs 200K) Visit [Swarms Platform Account](https://swarms.world/platform/account) to upgrade for just \$99/month. # Referral Program Source: https://docs.swarms.ai/docs/documentation/resources/referral Refer friends and you’ll both earn $20 in complimentary Swarms credits ## How It Works * **You earn \$20** when someone signs up with your link * **They earn \$20** when they join * **Win-win for everyone!** ## Getting Started ### 1. Get Your Link Go to [swarms.world/platform/referral](https://swarms.world/platform/referral) and copy your unique referral link. ### 2. Share It Share your link with friends, colleagues, or on social media: * Twitter * Facebook * LinkedIn * Instagram * Direct messaging ### 3. Earn Credits When someone signs up using your link, you both get \$20 in credits automatically. ## Track Your Progress Your dashboard shows: | Dashboard Metric | Description | | --------------------- | ------------------------------------------- | | **Total Signups** | How many people you've referred | | **Credits Earned** | Your total earnings (\$20 per referral) | | **Active Referrals** | Current active users | | **Referral Activity** | Detailed list with names, dates, and status | ## Quick Tips | Tip | | ---------------------------------------------------- | | ✅ **Share with people who need AI automation tools** | | ✅ **Explain the mutual \$20 benefit** | | ✅ **Use multiple channels to maximize reach** | | ✅ **Track your progress in the dashboard** | ## Rules * One bonus per email address * No self-referrals * Credits are automatically added when referrals complete signup * Use your exact referral link for proper tracking *** **Ready to start?** Get your link at [swarms.world/platform/referral](https://swarms.world/platform/referral) and start earning \$20 per referral today! # Overview Source: https://docs.swarms.ai/docs/documentation/resources/resources-overview A comprehensive guide to all Swarms API resources, documentation, and support materials. Welcome to the Swarms API Resources hub. This page provides quick access to all available resources in this section, helping you find exactly what you need to build, scale, and optimize your AI agents and swarms. ## Resource Directory | Resource | Description | Key Topics | | -------------------------------------------------------------------------- | ------------------------------------------------ | -------------------------------------------------- | | [Rate Limits](/docs/documentation/resources/ratelimits) | API request limits and throttling information | Request quotas, sliding windows, premium limits | | [Pricing](/docs/documentation/resources/pricing) | Pricing structure and credit deduction details | Subscription plans, usage-based pricing, discounts | | [Security](/docs/documentation/resources/security) | Security certifications and compliance standards | SOC 2, HIPAA, GDPR, data protection | | [Response Compression](/docs/documentation/resources/response-compression) | Optimize response sizes with compression | LZ4, Gzip, performance optimization | | [Premium Endpoints](/docs/documentation/resources/premium-endpoints) | Exclusive endpoints for paid tiers | Batch processing, advanced workflows | | [Priority Processing](/docs/documentation/resources/priority-processing) | Faster processing for priority requests | Queue prioritization, latency reduction | | [Global Availability](/docs/documentation/resources/global-availability) | Worldwide infrastructure and regions | Multi-region deployment, edge locations | | [Community](/docs/documentation/resources/community) | Connect with the Swarms community | Discord, social media, events | | [Technical Support](/docs/documentation/resources/technical-support) | Get help and support options | Support tiers, contact methods | | [Referral Program](/docs/documentation/resources/referral) | Earn credits by referring users | Referral rewards, program details | | [Contributors](/docs/documentation/resources/contributors) | Acknowledge our amazing contributors | Open source, community contributions | ## Quick Links by Category Essential resources for new users: * [Rate Limits](/docs/documentation/resources/ratelimits) - Understand API quotas * [Pricing](/docs/documentation/resources/pricing) - Choose the right plan * [Security](/docs/documentation/resources/security) - Review compliance Maximize your API efficiency: * [Response Compression](/docs/documentation/resources/response-compression) - Reduce payload sizes * [Priority Processing](/docs/documentation/resources/priority-processing) - Get faster responses * [Global Availability](/docs/documentation/resources/global-availability) - Leverage edge locations Unlock advanced capabilities: * [Premium Endpoints](/docs/documentation/resources/premium-endpoints) - Access exclusive APIs * [Priority Processing](/docs/documentation/resources/priority-processing) - Skip the queue Get help and connect: * [Community](/docs/documentation/resources/community) - Join Discord & social * [Technical Support](/docs/documentation/resources/technical-support) - Contact our team * [Referral Program](/docs/documentation/resources/referral) - Earn rewards ## Resource Highlights ### For Developers | What You Need | Go To | | ------------------------------------- | -------------------------------------------------------------------------- | | Understand API limits before building | [Rate Limits](/docs/documentation/resources/ratelimits) | | Optimize response times | [Response Compression](/docs/documentation/resources/response-compression) | | Deploy globally | [Global Availability](/docs/documentation/resources/global-availability) | ### For Teams & Enterprises | What You Need | Go To | | ---------------------------- | -------------------------------------------------------------------- | | Review security & compliance | [Security](/docs/documentation/resources/security) | | Explore premium features | [Premium Endpoints](/docs/documentation/resources/premium-endpoints) | | Get priority support | [Technical Support](/docs/documentation/resources/technical-support) | ### For Community Members | What You Need | Go To | | --------------------- | ---------------------------------------------------------- | | Join the community | [Community](/docs/documentation/resources/community) | | Start referring users | [Referral Program](/docs/documentation/resources/referral) | | Become a contributor | [Contributors](/docs/documentation/resources/contributors) | ## Need Help? Can't find what you're looking for? Join our [Discord community](https://discord.gg/EamjgSaEQf) or [book a support session](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) with our team. # Response Compression Source: https://docs.swarms.ai/docs/documentation/resources/response-compression The Swarms API automatically compresses HTTP responses using fast algorithms (LZ4, GZip) to reduce payload size and improve response times. The Swarms API uses intelligent response compression to significantly reduce payload sizes and improve response times. Responses are automatically compressed when beneficial, reducing bandwidth usage and speeding up data transfer. The API implements a dynamic compression middleware that automatically compresses HTTP responses based on: * **Response size**: Only compresses bodies larger than 500 bytes and no larger than 8 MiB * **Client support**: Negotiates the algorithm via the `Accept-Encoding` header (including q-values) * **Compression efficiency**: Only applies compression if it actually reduces the response size ## Supported Compression Algorithms The server prefers LZ4 for speed and falls back to GZip for universal compatibility: | Algorithm | Server Preference | Speed | Compression Ratio | Use Case | | --------- | ----------------- | ------------------ | ----------------- | ---------------------------------------------------------------- | | **LZ4** | Preferred | Very fast | Good balance | Fastest option for clients that can decode LZ4 frames | | **GZip** | Fallback | Moderate (level 6) | Excellent | Universal browser and client support — what most clients receive | Standard HTTP clients advertise `gzip` (not `lz4`) by default, so in practice most responses are GZip-compressed. LZ4 is only used when a client explicitly sends `lz4` in `Accept-Encoding` and can decode LZ4 frame data. ## How It Works ### Automatic Compression The compression middleware automatically: 1. **Parses client preferences**: Reads the `Accept-Encoding` header, ordering encodings by their q-values. An encoding with `q=0` is explicitly excluded; a `*` wildcard means any encoding is acceptable 2. **Selects the algorithm**: Walks the client's encodings in preference order and picks the first one the server supports. If only `*` matches, GZip is used, since every client can decode it 3. **Checks response size**: Only compresses bodies larger than 500 bytes and no larger than 8 MiB 4. **Validates compression**: Only applies if the compressed size is smaller than the original 5. **Sets headers**: Sets `Content-Encoding`, updates `Content-Length` to the compressed size, and appends `Accept-Encoding` to the `Vary` header ### Compression Flow ``` Request → Parse Accept-Encoding (q-values) → Select Algorithm → Check Size (500 bytes < body ≤ 8 MiB) → Compress → Validate → Return Compressed Response ``` ### Responses That Are Never Compressed The middleware passes these responses through unmodified: * **Streaming responses**, including Server-Sent Events (`text/event-stream`) — events must be flushed immediately, not buffered * **Already-encoded responses** — anything that already has a `Content-Encoding` header is never re-compressed * **Small responses** — bodies of 500 bytes or less * **Large responses** — bodies over 8 MiB (bounds server buffering memory) * **Responses where compression doesn't help** — if the compressed body isn't smaller, the original is returned ### Client Preferences The API respects client compression preferences through the `Accept-Encoding` header, including q-values: ```bash theme={null} Accept-Encoding: lz4, gzip;q=0.8, br;q=0 ``` In this example the client prefers LZ4, accepts GZip at lower priority, and explicitly refuses Brotli (`q=0`). The middleware: * Honors q-value ordering when choosing among supported methods * Treats `q=0` as "do not use this encoding" * Treats `*` as "any encoding" and responds with GZip, since every client can decode it * Returns the response uncompressed if no supported encoding is acceptable ## Benefits ### Performance Improvements | Benefit | Description | | ------------------------- | -------------------------------------------------- | | **Reduced Bandwidth** | Smaller payloads mean less data transfer | | **Faster Response Times** | Less data to transmit results in quicker responses | | **Lower Latency** | Especially beneficial for large JSON responses | | **Cost Savings** | Reduced bandwidth usage for both client and server | ### Automatic Optimization * **No configuration required**: Compression is automatic and transparent * **Smart fallback**: Automatically uses the best available method * **Size validation**: Only compresses when it actually helps * **Header management**: Properly sets compression headers for client compatibility ## Usage ### Standard HTTP Requests Compression works automatically with all API endpoints. No special configuration is needed — standard clients already send `Accept-Encoding: gzip` and decompress transparently: ```bash theme={null} curl --compressed \ -H "x-api-key: your-api-key" \ https://api.swarms.world/v1/models ``` ### Client Libraries Most HTTP clients automatically request and decompress GZip. Only opt into LZ4 if your client can decode LZ4 frame data: ```python theme={null} import requests # requests sends "Accept-Encoding: gzip, deflate" automatically # and transparently decompresses the response. response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": "your-api-key"}, json={ "agent_config": { "agent_name": "example", "model_name": "gpt-4o-mini", "max_loops": 1, }, "task": "Your task here", }, ) data = response.json() ``` ```python theme={null} import json import lz4.frame import requests # Explicitly request LZ4. requests does NOT decompress LZ4, # so decode the raw body manually. response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={ "x-api-key": "your-api-key", "Accept-Encoding": "lz4", }, json={ "agent_config": { "agent_name": "example", "model_name": "gpt-4o-mini", "max_loops": 1, }, "task": "Your task here", }, stream=True, ) body = response.raw.read() if response.headers.get("Content-Encoding") == "lz4": body = lz4.frame.decompress(body) data = json.loads(body) ``` ```javascript theme={null} // fetch negotiates gzip automatically and decompresses transparently. const response = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'x-api-key': 'your-api-key', 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_config: { agent_name: 'example', model_name: 'gpt-4o-mini', max_loops: 1 }, task: 'Your task here' }) }); const data = await response.json(); ``` ```bash theme={null} # --compressed sends "Accept-Encoding: gzip" and decodes the response curl --compressed \ -X POST https://api.swarms.world/v1/agent/completions \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "example", "model_name": "gpt-4o-mini", "max_loops": 1 }, "task": "Your task here" }' ``` ### Response Headers Compressed responses include these headers: ```http theme={null} Content-Encoding: gzip Content-Length: 1234 Vary: Accept-Encoding ``` * **Content-Encoding**: Indicates the compression method used (`gzip` or `lz4`) * **Content-Length**: Updated to the compressed size (smaller than the original) * **Vary**: `Accept-Encoding` is appended so caches store separate variants per encoding ## Compression Statistics The middleware logs compression details (at debug level) for monitoring: * Original response size * Compressed response size * Algorithm used ## Best Practices ### 1. Include Accept-Encoding Header Make sure your client sends an `Accept-Encoding` header (most do by default): ```bash theme={null} Accept-Encoding: gzip ``` Only add `lz4` if your client decodes LZ4 frames — e.g. `Accept-Encoding: lz4, gzip;q=0.8`. ### 2. Let Clients Handle Decompression Most HTTP clients automatically decompress responses. Don't manually decompress unless necessary. ### 3. Monitor Response Sizes Large responses benefit most from compression. The API automatically handles this optimization. ### 4. Use Modern Clients Modern HTTP clients (requests, fetch, axios) automatically handle compression and decompression. ## Technical Details ### Size Thresholds * **Minimum (500 bytes)**: Bodies of 500 bytes or less are not compressed — compression overhead exceeds the benefit for tiny payloads, where network latency is the bottleneck anyway * **Maximum (8 MiB)**: Bodies larger than 8 MiB are passed through uncompressed to bound the memory used for buffering responses on the server ### Compression Method Selection The middleware selects the compression method as follows: 1. **Client preference match**: Walks the client's `Accept-Encoding` entries in q-value order and uses the first method the server supports (`q=0` entries are skipped entirely) 2. **Wildcard support**: If the client accepts `*`, GZip is used, since every client can decode it 3. **No compression**: Returns the response uncompressed if no acceptable method is supported ### Error Handling If compression fails: * Original uncompressed response is returned * No error is raised to the client * Compression failure is logged for monitoring * Client receives valid response regardless ## Compatibility ### Browser Support All modern browsers support GZip compression automatically. LZ4 is not natively supported by browsers or most HTTP libraries — only request it if you decode it yourself. ### API Clients | Client | GZip Decompression | LZ4 Decompression | | ------------------ | ----------------------------- | ------------------------------- | | Python `requests` | Automatic | Manual (`lz4.frame.decompress`) | | JavaScript `fetch` | Automatic | Manual | | `curl` | Automatic with `--compressed` | Manual | | `axios` | Automatic | Manual | | `httpx` | Automatic | Manual (`lz4.frame.decompress`) | ## Summary The Swarms API's automatic response compression: * **Reduces bandwidth usage** by compressing responses * **Improves response times** through smaller payloads * **Works transparently** with no configuration needed * **Supports LZ4 and GZip**, preferring LZ4 for speed when the client accepts it * **Respects client preferences** via the Accept-Encoding header, including q-values (`q=0` excludes an encoding; `*` accepts any) * **Only compresses when it helps** — bodies between 500 bytes and 8 MiB, and only if the result is actually smaller * **Never touches streaming (SSE) or already-encoded responses** * **Compatible with all clients** that support standard HTTP compression Compression is automatic and requires no configuration. Simply make API requests as normal, and responses will be compressed when beneficial. # Security Source: https://docs.swarms.ai/docs/documentation/resources/security Swarms API security certifications and compliance standards. We take security very seriously. Security is the cornerstone of the Swarms platform. We maintain an unwavering commitment to the most rigorous security standards in the industry, implementing defense-in-depth strategies that protect your data, applications, and infrastructure at every layer. Our platform undergoes continuous security assessments, holds multiple industry-leading compliance certifications, and employs enterprise-grade controls that meet and exceed regulatory requirements across healthcare, financial services, government, and critical infrastructure sectors. Every API request, every agent execution, and every data transaction is protected by the same security architecture trusted by the world's most demanding organizations. ## Compliance We maintain the following security certifications and compliance standards: Certified for security, availability, processing integrity, confidentiality, and privacy controls. Public-facing report demonstrating our commitment to security and operational excellence. Compliant with Health Insurance Portability and Accountability Act requirements for healthcare data. Compliant with General Data Protection Regulation for European Union data protection standards. Certified under the EU-US Data Privacy Framework for transatlantic data transfers. Certified under the Swiss-US Data Privacy Framework for data transfers between Switzerland and the US. ## Security Commitment Our security certifications demonstrate our ongoing commitment to: * **Data Protection**: Comprehensive safeguards for all data processed through our platform * **Privacy Compliance**: Adherence to international privacy regulations and frameworks * **Operational Excellence**: Regular audits and assessments to maintain security standards * **Transparency**: Public reporting on our security practices and controls * **Enterprise Readiness**: Security measures designed for enterprise-scale deployments These certifications are regularly audited and maintained to ensure continuous compliance with evolving security standards and regulations. # Technical Support Source: https://docs.swarms.ai/docs/documentation/resources/technical-support Get comprehensive technical support for Swarms API | Support Level | Description | Response Time | Cost | Link | | ------------------- | ------------------------------------------------------- | --------------- | ---- | ------------------------------------------------------------------------------------ | | Discord Community | Real-time community support and general questions | Immediate | Free | [Join Discord](https://discord.gg/EamjgSaEQf) | | Discord Tickets | Specific technical issues requiring dedicated attention | Within 24 hours | Free | [Create Ticket](https://discord.gg/EamjgSaEQf) | | One-on-One Sessions | Personalized technical support with Kye Gomez | Scheduled | Paid | [Book Session](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) | | Onboarding | New user guidance and setup assistance | Scheduled | Paid | [Book Onboarding](https://cal.com/swarms/swarms-onboarding-session) | # Usage Report Source: https://docs.swarms.ai/docs/documentation/resources/usage-report API reference for the GET /v1/usage/costs endpoint — retrieve the current per-operation pricing used to calculate your usage costs. There is no dedicated endpoint that returns a historical, day-by-day breakdown of your spend. The Swarms API exposes the **current pricing model** via `/v1/usage/costs`, plus a handful of related endpoints for checking your balance and activity — see [Related Endpoints](#related-endpoints) below. The Usage endpoint returns the unified pricing model the API uses to calculate costs for every operation (token costs, agent costs, search/scrape costs, and the night-time discount). Use it to compute expected costs before you run a request, or to keep your own cost estimates in sync with the live pricing. ## Endpoint Information * **URL**: `/v1/usage/costs` * **Method**: `GET` * **Authentication**: Required (`x-api-key` header) * **Rate Limiting**: Subject to tier-based rate limits *** ## Query Parameters None. This endpoint always returns the current pricing model in effect. *** ## Code Examples ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } response = requests.get(f"{BASE_URL}/v1/usage/costs", headers=headers) data = response.json() pricing = data["usage_pricing"] print(f"Agent completions input cost: ${pricing['agent_completions_input_cost_per_1m']} / 1M tokens") print(f"Agent completions output cost: ${pricing['agent_completions_output_cost_per_1m']} / 1M tokens") ``` ```typescript theme={null} import "dotenv/config"; const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; if (!API_KEY) { throw new Error("SWARMS_API_KEY is not set"); } const res = await fetch(`${BASE_URL}/v1/usage/costs`, { method: "GET", headers: { "x-api-key": API_KEY, "Content-Type": "application/json", }, }); if (!res.ok) { throw new Error(`HTTP ${res.status}: ${await res.text()}`); } const data = await res.json(); console.log(data.usage_pricing); ``` ```bash theme={null} curl -X GET "https://api.swarms.world/v1/usage/costs" \ -H "x-api-key: $SWARMS_API_KEY" ``` *** ## Response Schema ### PricingDetailsOutput Object | Field | Type | Description | | --------------- | -------- | -------------------------------------------------------------------------------------------- | | `usage_pricing` | `object` | All per-operation costs — token costs, agent costs, search/scrape costs, night-time discount | | `timestamp` | `string` | ISO timestamp when the pricing information was retrieved | ### usage\_pricing Object | Field | Type | Description | | -------------------------------------- | -------- | ------------------------------------------------------------------------------------------- | | `swarm_completions_agent_cost` | `number` | Cost per agent in swarm completions (USD) | | `swarm_completions_input_cost_per_1m` | `number` | Cost per 1M input tokens for swarm completions (USD) | | `swarm_completions_output_cost_per_1m` | `number` | Cost per 1M output tokens for swarm completions (USD) | | `agent_completions_input_cost_per_1m` | `number` | Cost per 1M input tokens for agent completions (USD) | | `agent_completions_output_cost_per_1m` | `number` | Cost per 1M output tokens for agent completions (USD) | | `agent_completions_img_cost` | `number` | Cost per image for agent completions (USD) | | `agent_completions_mcp_cost` | `number` | Cost per MCP call for agent completions (USD) | | `search_cost` | `number` | Cost per search operation (USD) | | `scrape_cost` | `number` | Cost per scrape operation (USD) | | `night_time_discount` | `number` | Discount multiplier applied to swarm completion token costs, 8 PM - 6 AM PT (0.5 = 50% off) | ### Example Response ```json theme={null} { "usage_pricing": { "swarm_completions_agent_cost": 0.01, "swarm_completions_input_cost_per_1m": 6.5, "swarm_completions_output_cost_per_1m": 18.5, "agent_completions_input_cost_per_1m": 6.5, "agent_completions_output_cost_per_1m": 18.5, "agent_completions_img_cost": 0.25, "agent_completions_mcp_cost": 0.1, "search_cost": 0.04, "scrape_cost": 0.15, "night_time_discount": 0.5 }, "timestamp": "2026-03-29T18:30:00+00:00" } ``` *** ## Error Responses | HTTP Status | Cause | | ----------- | --------------------------------------------- | | 401 | Missing or invalid API key | | 429 | Rate limit exceeded | | 500 | Internal error retrieving pricing information | *** ## Related Endpoints For actual usage and spend tracking (rather than the pricing model itself), use: | Need | Endpoint | Returns | | --------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------- | | Current credit balance | `GET /v1/account/credits` | `credit`, `free_credit`, `referral_credits`, `total_credits` | | Lifetime/recent completion counts | `GET /v1/account/metrics/summary` | Unique agents used, lifetime and successful completion counts, completions in the last 24h/7d | | Raw request history | `GET /v1/swarm/logs` | All logged API requests for your account, which you can aggregate client-side into a custom report | | Current rate limit usage | `GET /v1/rate/limits` | Requests used/remaining per minute, hour, and day | Billable completion endpoints require your `total_credits` balance to be above \$1.00. This is checked before the request runs — if the balance is at or below the minimum, the API returns a **402 Payment Required** error without doing any work. Use `GET /v1/account/credits` to monitor your balance. *** ## Related * [Get Credit Balance](/docs/examples/examples/account-credits) — check your current credit balance * [Pricing Details](/docs/examples/examples/pricing-details-basic) — see per-operation costs * [Rate Limits](/docs/examples/api_examples/rate_limits) — check rate limit status # Workflow Builder Source: https://docs.swarms.ai/docs/documentation/workflow-builder/overview Visually design, run, and export multi-agent workflows on Swarms Cloud. Drag agents onto a canvas, connect them into a directed graph, then run on the platform or export the request as code. Premium: The Workflow Builder runs on the Graph Workflow Completions API, which is available only on Pro, Ultra, and Premium plans. See Pricing. ## Overview The Workflow Builder (`https://swarms.world/platform/workflow-builder`) is a visual editor for building multi-agent systems on Swarms Cloud. Agents are nodes on a canvas, and the connections between them define how work flows from one agent to the next. Instead of writing orchestration code by hand, you compose the system visually: drag agents onto the canvas, configure each one, wire them into a directed graph, and run the whole thing in one click. What you build is backed by the [Graph Workflow Completions API](/docs/documentation/multi-agent/graph_workflow), so anything you can draw you can also run in production. When a workflow is ready, you can execute it directly in the interface or export the exact API request as Python, TypeScript, Go, or cURL. ## Key Features * **Visual canvas**: Drag, drop, and connect agents into sequential, parallel, or multi-layer graphs * **Full agent configuration**: Set any model, system prompt, role, temperature, tokens, reasoning, tools, MCP, and autonomous looping per node * **One-click execution**: Run the entire graph on the platform and inspect each node's output * **Export to code**: Generate the equivalent request in Python, TypeScript, Go, cURL, or raw JSON * **Automatic entry and end points**: Start and finish nodes are derived from the graph topology * **Live request preview**: The exported code updates as you edit the graph, so the canvas and the code always stay in sync ## Interface Overview The builder is a full-screen canvas with a few floating controls: * **Top toolbar**: Workflow name, plus actions to add an agent, open settings, view the exported code, and view run output * **Canvas**: The graph itself, with pan, zoom, a minimap, and standard zoom controls * **Node inspector**: A side panel for configuring the selected agent * **Task bar**: A docked bar at the bottom for the workflow task and the Run button ## Building a Workflow Click **Add agent** to drop a new node onto the canvas. Each node represents one agent and uses its name as its unique node ID. Select a node to open the inspector, then set its model, system prompt, role, and generation parameters. See [Configuring an Agent](#configuring-an-agent) for the full list of options. Drag from a node's right handle to another node's left handle to create an edge. The edge defines the direction work flows. Build sequential chains, fan several agents into one, or fan one out to many. Enter the task for the workflow in the bottom bar. This is the instruction the graph executes. Click **Run** to execute on the platform and view each node's output, or open the **Code** panel to export the request in your language of choice. ## Configuring an Agent Each node exposes the full agent schema. The model field accepts any model id the platform supports, not just the presets. | Setting | Description | | ----------------------------- | ---------------------------------------------------------------------------------------------- | | `agent_name` | Unique name that identifies the node in the graph | | `model_name` | Any supported model id, for example `gpt-4.1`, `openai/o3-mini`, or `claude-sonnet-4-20250514` | | `system_prompt` | Instruction that guides the agent's behavior | | `description` | Short summary of the agent's purpose | | `role` | Role within the workflow, such as worker or analyst | | `temperature` | Controls randomness of the output | | `max_tokens` | Maximum tokens the agent can generate | | `max_loops` | Fixed iteration count, or `auto` for autonomous looping until the task is complete | | `auto_generate_prompt` | Let the agent write its own system prompt from the task | | `dynamic_temperature_enabled` | Adjust temperature automatically per task | | `streaming_on` | Stream output tokens as they are produced | | `reasoning_enabled` | Enable reasoning, with `reasoning_effort` and `thinking_tokens` | | `tool_call_summary` | Summarize tool-call output | | `mcp_url` | Connect the agent to an MCP server | | `selected_tools` | Restrict the autonomous looper to a chosen set of tools | | `llm_args` | Extra model arguments such as `top_p` or `frequency_penalty` | Set `max_loops` to `auto` to turn a node into an autonomous agent that decides how many steps it needs. When autonomous, you can restrict it to specific tools with `selected_tools`. ## Entry and End Points You do not need to declare which nodes start or finish the workflow. The builder derives them from the graph: * **Entry points** are nodes with no incoming edge * **End points** are nodes with no outgoing edge These are shown as badges on the canvas and sent automatically as `entry_points` and `end_points` in the request. ## Running on the Platform Click **Run** to execute the graph through the Graph Workflow Completions API. The output panel shows: * Each node's output, keyed by agent name * Total token usage and cost for the run ## Exporting to Code The **Code** panel mirrors the exact request the platform sends, and updates live as you edit the graph. Switch between Python, TypeScript, Go, cURL, and JSON, then copy the snippet into your application. This is the same payload documented in the [Graph Workflow Completions API](/docs/documentation/multi-agent/graph_workflow). A typical exported request looks like this: ```python theme={null} theme={null} import os import requests payload = { "name": "Research-Analysis-Workflow", "agents": [ { "agent_name": "ResearchAgent", "model_name": "gpt-4.1", "role": "worker", "system_prompt": "You are an expert researcher.", "max_loops": 1, "max_tokens": 4000, "temperature": 0.3, }, { "agent_name": "AnalysisAgent", "model_name": "gpt-4.1", "role": "analyst", "system_prompt": "You analyze research and extract key insights.", "max_loops": 1, "max_tokens": 4000, "temperature": 0.3, }, ], "edges": [ {"source": "ResearchAgent", "target": "AnalysisAgent"}, ], "entry_points": ["ResearchAgent"], "end_points": ["AnalysisAgent"], "task": "What are the latest trends in AI development?", "auto_compile": True, } response = requests.post( "https://api.swarms.world/v1/graph-workflow/completions", headers={ "x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json", }, json=payload, ) response.raise_for_status() print(response.json()) ``` ## Best Practices * **Use descriptive agent names**: Names are node IDs and must be unique, so make them specific * **Keep prompts focused**: One strong instruction per agent beats several weak ones * **Prototype visually, ship as code**: Build and test in the canvas, then export the request into your own service * **Choose models per task**: Use stronger models for synthesis and lighter models for simple steps to control cost ## Availability The Workflow Builder is available to Pro, Ultra, and Premium users. For details on Graph Workflow pricing and limits, see the [Pricing](/docs/documentation/resources/pricing) page. ## Related The API that powers the Workflow Builder. Explore every multi-agent architecture in the Swarms API. # Single Agent Completion (REST) Source: https://docs.swarms.ai/docs/examples/api_examples/agent_completion_single_agent Python example using the Agent Completions endpoint to run a single research agent with the new AgentCompletion format. ## Overview Use the **Agent Completions** endpoint (`/v1/agent/completions`) to run a single, well‑configured agent for a specific task.\ This example shows a **Research Analyst** agent that uses the new `agent_config` shape and returns a structured JSON response. This example is a companion to the main reference at `/docs/documentation/capabilities/agent`.\ It focuses on a minimal, production‑ready Python script using plain `requests`. ## Prerequisites * **Python 3.9+** * A valid **Swarms API key** Create a `.env` file in your project root: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` Install dependencies: ```bash theme={null} pip install python-dotenv requests ``` ## Run a Single Agent Completion ```python theme={null} import os import requests from dotenv import load_dotenv import json load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def run_single_agent(): """Run a single agent with the Agent Completions format""" payload = { "agent_config": { "agent_name": "Research Analyst", "description": "An expert in analyzing and synthesizing research data", "system_prompt": ( "You are a Research Analyst with expertise in data analysis and synthesis. " "Your role is to analyze provided information, identify key insights, " "and present findings in a clear, structured format. " "Focus on accuracy, clarity, and actionable recommendations." ), "model_name": "gpt-4.1", "role": "worker", # For simple, single-shot tasks you can keep max_loops at 1. # Use 'auto' for autonomous multi-step behavior (see autonomous tutorial). "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": False, "dynamic_temperature_enabled": True, }, "task": "What are the best ways to find samples of diabetes from blood samples?", } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60, ) response.raise_for_status() return response.json() if __name__ == "__main__": result = run_single_agent() print(json.dumps(result, indent=4)) ``` ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } async function runSingleAgent() { const payload = { agent_config: { agent_name: 'Research Analyst', description: 'An expert in analyzing and synthesizing research data', system_prompt: 'You are a Research Analyst with expertise in data analysis and synthesis. ' + 'Your role is to analyze provided information, identify key insights, ' + 'and present findings in a clear, structured format. ' + 'Focus on accuracy, clarity, and actionable recommendations.', model_name: 'gpt-4.1', role: 'worker', max_loops: 1, max_tokens: 8192, temperature: 0.7, auto_generate_prompt: false, dynamic_temperature_enabled: true, }, task: 'What are the best ways to find samples of diabetes from blood samples?', } const res = await fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY, }, body: JSON.stringify(payload), }) if (!res.ok) { const text = await res.text() throw new Error(`HTTP ${res.status}: ${text}`) } const json = await res.json() console.log(JSON.stringify(json, null, 2)) } void runSingleAgent().catch(console.error) ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let payload = json!({ "agent_config": { "agent_name": "Research Analyst", "description": "An expert in analyzing and synthesizing research data", "system_prompt": "You are a Research Analyst with expertise in data analysis and synthesis. \ Your role is to analyze provided information, identify key insights, \ and present findings in a clear, structured format. \ Focus on accuracy, clarity, and actionable recommendations.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.7, "auto_generate_prompt": false, "dynamic_temperature_enabled": true }, "task": "What are the best ways to find samples of diabetes from blood samples?" }); let res = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&payload) .send()?; res.error_for_status_ref()?; let body = res.text()?; println!("{body}"); Ok(()) } ``` ### What This Example Shows * **New `agent_config` format** matching the Agent Completions reference * A **single, stateless request** to `/v1/agent/completions` * How to **inspect the full JSON response**, including `outputs` and `usage` ### Next Steps * Add `history` or `tools_enabled` (e.g. `["auto_search"]`) for more advanced behaviors * Use `max_loops="auto"` with the higher‑level `Agent` class for fully autonomous workflows\ → See **“Autonomous Agents with `max_loops="auto"`”** in the examples section. # Fully Autonomous Agent Loop Source: https://docs.swarms.ai/docs/examples/api_examples/autonomous_agent_tutorial Tutorial for building fully autonomous agents that plan, execute, and summarize multi-step tasks using max_loops="auto". ## Overview The **autonomous agent mode** (`max_loops="auto"`) lets an agent **plan, execute, and summarize complex multi‑step tasks** without you having to manually specify the number of loops. When `max_loops="auto"`, the agent: * **Plans** the work as a set of structured subtasks * **Executes** each subtask using tools (search, file I/O, etc.) * **Summarizes** the results into a clear final answer This page walks through a **fully autonomous medical diagnosis agent** that analyzes blood work results using the Swarms Python client. ## How Autonomous Mode Works ```mermaid theme={null} flowchart TD A[Task Received] --> B[Planning Phase] B --> C{Plan Created?} C -- No --> B C -- Yes --> D[Execution Phase] D --> E{Next Executable Subtask?} E -- No --> H[Summary Phase] E -- Yes --> F[Subtask Execution Loop] F --> F1[Think & Analyze] F1 --> F2[Call Tools / APIs] F2 --> F3[Observe Results] F3 --> G{Subtask Complete?} G -- No --> F1 G -- Yes --> E H --> I[Generate Final Summary] I --> J[Return Results] ``` ### Phase 1: Planning * The agent analyzes the main task and calls an internal planning tool (e.g., `create_plan`) * It produces a list of **subtasks** with: * `step_id`: unique identifier * `description`: what to do * `priority`: `critical`, `high`, `medium`, or `low` * `dependencies`: other steps that must complete first ### Phase 2: Execution For each subtask, the agent loops through: 1. **Think**: Optional short reasoning step (e.g., with a `think` tool) 2. **Act**: Calls tools (search, file, APIs, etc.) 3. **Observe**: Reads tool outputs and updates its plan state 4. **Complete**: Marks the subtask done when satisfied (e.g., via `subtask_done`) Dependencies are respected — subtasks only run when their prerequisites are complete. ### Phase 3: Summary Once all subtasks are complete, the agent: * Generates a **final structured summary** * Optionally calls a completion tool (e.g., `complete_task`) * Returns the final result to your application ### Tool Selection By default, autonomous agents have access to all safe built-in tools. You can restrict which tools are available using the `selected_tools` parameter in `agent_config`: ```python theme={null} payload = { "agent_config": { "agent_name": "My Agent", "model_name": "gpt-4.1", "max_loops": "auto", "selected_tools": ["create_plan", "think", "subtask_done", "complete_task", "read_file"], }, "task": "Your task here", } ``` Available tools: `create_plan`, `think`, `subtask_done`, `complete_task`, `respond_to_user`, `create_file`, `update_file`, `read_file`, `list_directory`, `delete_file`, `create_sub_agent`, `assign_task`. `run_bash` is not available via the API for security reasons. ## Complete Example: Autonomous Medical Diagnosis Agent This example shows an autonomous agent that: * Uses the **Swarms Python client** to call the Agent Completions API * Analyzes **blood work results** as an expert doctor * Runs until it decides the task is complete using `max_loops="auto"` ### Environment Setup Create a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_swarms_api_key_here ``` Install dependencies: ```bash theme={null} pip install swarms-client python-dotenv ``` ### Code Example ```python theme={null} import os from dotenv import load_dotenv import json from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) result = client.agent.run( agent_config={ "agent_name": "Bloodwork Diagnosis Expert", "description": "An expert doctor specializing in interpreting and diagnosing blood work results.", "system_prompt": ( "You are an expert medical doctor specializing in the interpretation and diagnosis of blood work. " "Your expertise includes analyzing laboratory results, identifying abnormal values, " "explaining their clinical significance, and recommending next diagnostic or treatment steps. " "Provide clear, evidence-based explanations and consider differential diagnoses based on blood test findings." ), "model_name": "gpt-4.1", "max_loops": "auto", # <— enables fully autonomous multi-step reasoning "max_tokens": 1000, "temperature": 0.5, }, task=( "A patient presents with the following blood work results: " "Hemoglobin: 10.2 g/dL (low), WBC: 13,000 /µL (high), Platelets: 180,000 /µL (normal), " "ALT: 65 U/L (high), AST: 70 U/L (high). " "Please provide a detailed interpretation, possible diagnoses, and recommended next steps." ), ) print(json.dumps(result, indent=4)) ``` ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } async function runAutonomousAgent() { const payload = { agent_config: { agent_name: 'Research-Report-Agent', description: 'Creates comprehensive research reports', system_prompt: 'You are an expert research analyst. ' + 'Create detailed, well-structured reports and save work to files when appropriate.', model_name: 'gpt-4.1', max_loops: 'auto', // enable autonomous loop mode dynamic_temperature_enabled: true, }, task: ` Create a comprehensive research report on quantum computing: 1. Research current quantum computing technologies. 2. Identify major companies and research institutions. 3. Analyze recent breakthroughs. 4. Predict future trends. 5. Create a detailed markdown-style outline. `, } const res = await fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY, }, body: JSON.stringify(payload), }) if (!res.ok) { const text = await res.text() throw new Error(`HTTP ${res.status}: ${text}`) } const json = await res.json() console.log(JSON.stringify(json, null, 2)) } void runAutonomousAgent().catch(console.error) ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let payload = json!({ "agent_config": { "agent_name": "Research-Report-Agent", "description": "Creates comprehensive research reports", "system_prompt": "You are an expert research analyst. \ Create detailed, well-structured reports and save work to files when appropriate.", "model_name": "gpt-4.1", "max_loops": "auto", "dynamic_temperature_enabled": true }, "task": "\ Create a comprehensive research report on quantum computing:\n\ 1. Research current quantum computing technologies.\n\ 2. Identify major companies and research institutions.\n\ 3. Analyze recent breakthroughs.\n\ 4. Predict future trends.\n\ 5. Create a detailed markdown-style outline.\n\ " }); let res = client .post("https://api.swarms.world/v1/agent/completions") .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&payload) .send()?; res.error_for_status_ref()?; let body = res.text()?; println!("{body}"); Ok(()) } ``` ## Best Practices * **Clear tasks**: Give specific, outcome‑oriented instructions (what to produce, how many steps) * **Tooling**: Provide tools that match the work (search, scraping, file I/O, custom APIs) * **Bounded scope**: Ask for a concrete deliverable (e.g., “single markdown report”, “CSV summary”) ## Key Takeaways * Set **`max_loops="auto"`** to let the agent decide how many reasoning/action loops are required * Combine **planning, tools, and file operations** to tackle complex research and analysis workflows * Prefer **clear, structured tasks** so the planner can create good subtasks and dependencies For a minimal REST‑only example using `/v1/agent/completions`, see **“Single Agent Completion (REST)”** in the examples section. # Client Example Source: https://docs.swarms.ai/docs/examples/api_examples/client_example Python code example for setting up the Swarms API client and performing basic operations. ## Overview This example demonstrates how to set up the Swarms API client and perform basic operations like checking health, models, and rate limits. ## Step 1: Installation Install the required package: ```bash theme={null} pip install swarms-client python-dotenv ``` ## Step 2: API Key Setup Set your API key in a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Step 3: Code Example ```python theme={null} import os import json from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) print(json.dumps(client.models.list_available(), indent=4)) print(json.dumps(client.health.check(), indent=4)) print(json.dumps(client.swarms.get_logs(), indent=4)) print(json.dumps(client.client.rate.get_limits(), indent=4)) print(json.dumps(client.swarms.check_available(), indent=4)) ``` Run the script to see available models, API health, swarm logs, rate limits, and swarm availability. # Legal Team Example Source: https://docs.swarms.ai/docs/examples/api_examples/legal_team Python code example for creating a multi-agent legal document review swarm using the Swarms API. ## Overview This example demonstrates how to create a multi-agent swarm for legal document review and analysis using the Swarms API. ## Step 1: Installation Install the required packages: ```bash theme={null} pip install requests python-dotenv ``` ## Step 2: API Key Setup Set your API key in a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Step 3: Code Example ```python theme={null} """Legal team module for document review and analysis using Swarms API.""" import os from dotenv import load_dotenv import requests # Load environment variables load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"} def run_swarm(swarm_config): """Execute a swarm with the provided configuration. Args: swarm_config (dict): Configuration dictionary for the swarm. Returns: dict: Response from the Swarms API. """ response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=HEADERS, json=swarm_config, ) return response.json() def create_legal_review_swarm(document_text): """Create a multi-agent legal document analysis swarm. Args: document_text (str): The legal document text to analyze. Returns: dict: Results from the legal document analysis swarm. """ STRUCTURE_ANALYST_PROMPT = """ You are a legal document structure specialist. Your task is to analyze the organization and formatting of the document. - Identify the document type and its intended purpose. - Outline the main structural components (e.g., sections, headers, annexes). - Point out any disorganized, missing, or unusually placed sections. - Suggest improvements to the document's layout and logical flow. """ PARTY_IDENTIFIER_PROMPT = """ You are an expert in identifying legal parties and roles within documents. Your task is to: - Identify all named parties involved in the agreement. - Clarify their roles (e.g., buyer, seller, employer, employee, licensor, licensee). - Highlight any unclear party definitions or relationships. """ CLAUSE_EXTRACTOR_PROMPT = """ You are a legal clause and term extraction agent. Your role is to: - Extract key terms and their definitions from the document. - Identify standard clauses (e.g., payment terms, termination, confidentiality). - Highlight missing standard clauses or unusual language in critical sections. """ AMBIGUITY_CHECKER_PROMPT = """ You are a legal risk and ambiguity reviewer. Your role is to: - Flag vague or ambiguous language that may lead to legal disputes. - Point out inconsistencies across sections. - Highlight overly broad, unclear, or conflicting terms. - Suggest clarifying edits where necessary. """ COMPLIANCE_REVIEWER_PROMPT = """ You are a compliance reviewer with expertise in regulations and industry standards. Your responsibilities are to: - Identify clauses required by applicable laws or best practices. - Flag any missing mandatory disclosures. - Ensure data protection, privacy, and consumer rights are addressed. - Highlight potential legal or regulatory non-compliance risks. """ swarm_config = { "name": "Legal Document Review Swarm", "description": "A collaborative swarm for reviewing contracts and legal documents.", "agents": [ { "agent_name": "Structure Analyst", "description": "Analyzes document structure and organization", "system_prompt": STRUCTURE_ANALYST_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Party Identifier", "description": "Identifies parties and their legal roles", "system_prompt": PARTY_IDENTIFIER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Clause Extractor", "description": "Extracts key terms, definitions, and standard clauses", "system_prompt": CLAUSE_EXTRACTOR_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Ambiguity Checker", "description": "Flags ambiguous or conflicting language", "system_prompt": AMBIGUITY_CHECKER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Compliance Reviewer", "description": "Reviews document for compliance with legal standards", "system_prompt": COMPLIANCE_REVIEWER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, ], "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": f"Perform a legal document review and provide structured analysis of the following contract:\n\n{document_text}", } return run_swarm(swarm_config) def run_legal_review_example(): """Run an example legal document analysis. Returns: dict: Results from analyzing the example legal document. """ document = """ SERVICE AGREEMENT This Service Agreement ("Agreement") is entered into on June 15, 2024, by and between Acme Tech Solutions ("Provider") and Brightline Corp ("Client"). 1. Services: Provider agrees to deliver IT consulting services as outlined in Exhibit A. 2. Compensation: Client shall pay Provider $15,000 per month, payable by the 5th of each month. 3. Term & Termination: The Agreement shall remain in effect for 12 months and may be terminated with 30 days' notice by either party. 4. Confidentiality: Each party agrees to maintain the confidentiality of proprietary information. 5. Governing Law: This Agreement shall be governed by the laws of the State of California. IN WITNESS WHEREOF, the parties have executed this Agreement as of the date first above written. """ result = create_legal_review_swarm(document) print(result) return result if __name__ == "__main__": run_legal_review_example() ``` Run the script to analyze legal documents using a multi-agent swarm with specialized roles for structure analysis, party identification, clause extraction, ambiguity checking, and compliance review. # Rate Limits Example Source: https://docs.swarms.ai/docs/examples/api_examples/rate_limits Python code example for checking API rate limits and health status using the Swarms API. ## Overview This example demonstrates how to check API rate limits and health status using the Swarms API client. ## Step 1: Installation Install the required package: ```bash theme={null} pip install swarms-client python-dotenv ``` ## Step 2: API Key Setup Set your API key in a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Step 3: Code Example ```python theme={null} from swarms_client import SwarmsClient from dotenv import load_dotenv import os load_dotenv() client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) response = client.client.rate.get_limits() print(response) print(client.health.check()) ``` Run the script to check your current rate limits and API health status. # 13F Tracker: Quarterly Hedge Fund Position Changes at Scale Source: https://docs.swarms.ai/docs/examples/examples/13f-tracker-quarterly-burst Parse ~5,000 13F filings in a 48-hour quarterly burst with a fan-out GraphWorkflow, then synthesize cross-fund themes into a newsroom-ready brief — for the cost of takeout dinner. ## What This Example Shows * A `GraphWorkflow` shaped as fan-out → fan-in: thousands of per-fund parser nodes run in parallel, then converge into a cross-fund aggregator and a Theme Synthesizer * How to parse raw SEC EDGAR 13F-HR filings (CIK + accession number) into structured holdings, then diff against the prior quarter * The batch volume math for the quarterly burst: \~5,000 filings dropping in 48 hours, dispatched concurrently against `/v1/graph-workflow/completions` and priced under night-mode * Model diversification across the DAG: `gpt-4.1-mini` for mechanical parsing, `gpt-4.1` for aggregation, `claude-sonnet-4.5` for the synthesis layer * Journalist-grade output: ranked sector adds/cuts, new positions crossing \$100M of cumulative flow, eliminated positions, and named emerging themes with the funds driving them * A reusable pattern for any high-volume regulatory-filing burst (Form 4, N-PORT, NPX) This tutorial leans hard on two premium features: the graph workflow endpoint (`/v1/graph-workflow/completions`), dispatched concurrently across the filing list for the burst, and **night-mode pricing** for the burst itself. 13Fs become public after-hours on the 45-day lag — fire the burst between 8pm and 6am Pacific and you pay the night-mode rate. Read the [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) guide for the schedule. ## Why This Matters Form 13F-HR filings publish on a 45-day lag — every institutional manager with over \$100M AUM has to disclose their long US-equity positions within 45 days of quarter-end, and almost all of them file in the same 48-hour window right at the deadline. \~5,000 filings hit EDGAR essentially simultaneously, and that window is when the entire allocator and newsroom ecosystem scrambles: Bloomberg, the FT, Institutional Investor, fund-of-funds managers, sell-side strategists, and signal traders are all racing to surface "what did the smart money buy" before the next morning's open. The traditional shape of that work is a junior analyst manually pulling a handful of "name brand" 13Fs (Pershing Square, Tiger, Coatue, Berkshire) and writing one-off blurbs — leaving 4,990 filings unread and the cross-fund themes invisible. A GraphWorkflow turns the firehose into a structured story automatically: every filing parsed, every position diffed, every theme ranked by cumulative dollar flow across all reporting managers. By 7am Pacific on day 2 of the window, you have a brief that took a newsroom team two weeks the old way. ## The Architecture ```text theme={null} GraphWorkflow ┌─────────────────────────────────┐ EDGAR 13F feed (~5,000 CIKs) │ │ │ │ [13F Parser — Fund 1] ──┐ │ ▼ │ [13F Parser — Fund 2] ──┤ │ [Batch Dispatcher] ────────► │ [13F Parser — Fund 3] ──┼──► │ (one swarm │ … │ │ payload per │ [13F Parser — Fund N] ──┘ │ filing) │ │ │ │ ▼ │ │ [Cross-Fund Aggregator] │ │ │ │ │ ▼ │ │ [Theme Synthesizer] │ └───────────┬─────────────────────┘ │ ▼ Markdown brief per theme + Top-N adds/cuts per manager │ ▼ Postgres / Slack ``` Per-fund parsing happens in parallel inside each filing's own GraphWorkflow. The batch dispatcher fans the workload out across the 5,000 filings. The synthesis is the cross-cutting layer that runs once across the batched outputs. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os from concurrent.futures import ThreadPoolExecutor, as_completed from datetime import datetime from pathlib import Path import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Every tool the parser and aggregator nodes use is declared as an OpenAI-style function tool. The model calls them, the runtime resolves them on your side. ```python theme={null} FETCH_13F_FILING = { "type": "function", "function": { "name": "fetch_13f_filing", "description": ( "Download the raw 13F-HR filing for a given CIK and accession number " "from SEC EDGAR and return the holdings table as text." ), "parameters": { "type": "object", "properties": { "cik": { "type": "string", "description": "SEC CIK (Central Index Key) of the filing manager, zero-padded to 10 digits.", }, "accession": { "type": "string", "description": "EDGAR accession number, e.g. '0001172661-24-000123'.", }, }, "required": ["cik", "accession"], }, }, } PARSE_13F_HOLDINGS = { "type": "function", "function": { "name": "parse_13f_holdings", "description": ( "Parse the raw informationTable.xml body of a 13F-HR filing into a " "list of holdings with ticker, CUSIP, issuer, shares, and market value." ), "parameters": { "type": "object", "properties": { "filing_text": { "type": "string", "description": "Raw XML or text body of the 13F informationTable.", } }, "required": ["filing_text"], }, }, } LOOKUP_FUND_PROFILE = { "type": "function", "function": { "name": "lookup_fund_profile", "description": ( "Return the fund's name, AUM bucket, strategy tag (e.g. long-short, " "activist, quant, family office), and known PM." ), "parameters": { "type": "object", "properties": { "cik": {"type": "string", "description": "Manager CIK."}, }, "required": ["cik"], }, }, } DIFF_QUARTER_HOLDINGS = { "type": "function", "function": { "name": "diff_quarter_holdings", "description": ( "Compute position deltas between this quarter and the prior quarter. " "Returns adds, trims, new positions, and eliminated positions with " "share-count and market-value changes." ), "parameters": { "type": "object", "properties": { "this_q": { "type": "array", "description": "Holdings array for the current quarter.", "items": {"type": "object"}, }, "last_q": { "type": "array", "description": "Holdings array for the prior quarter.", "items": {"type": "object"}, }, }, "required": ["this_q", "last_q"], }, }, } CROSS_FUND_AGGREGATE = { "type": "function", "function": { "name": "cross_fund_aggregate", "description": ( "Aggregate per-fund adds and cuts into cross-fund sector flows. " "Sums cumulative dollar inflow/outflow per ticker and per GICS sector." ), "parameters": { "type": "object", "properties": { "adds_by_sector": { "type": "object", "description": "Map of sector → list of {ticker, fund_cik, dollar_change}.", }, "cuts_by_sector": { "type": "object", "description": "Map of sector → list of {ticker, fund_cik, dollar_change}.", }, }, "required": ["adds_by_sector", "cuts_by_sector"], }, }, } IS_NEW_POSITION = { "type": "function", "function": { "name": "is_new_position", "description": ( "Check whether a ticker is a brand-new position for the fund by " "scanning the fund's prior 8 quarters of holdings history." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string", "description": "Equity ticker."}, "fund_history": { "type": "array", "description": "Array of prior-quarter holdings arrays for this fund.", "items": {"type": "object"}, }, }, "required": ["ticker", "fund_history"], }, }, } POST_THEME_BRIEF_TO_SLACK = { "type": "function", "function": { "name": "post_theme_brief_to_slack", "description": ( "Post a rendered Markdown theme brief to the #13f-tracker Slack channel." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "Rendered Markdown body of the theme brief.", } }, "required": ["text"], }, }, } PARSER_TOOLS = [FETCH_13F_FILING, PARSE_13F_HOLDINGS, LOOKUP_FUND_PROFILE, DIFF_QUARTER_HOLDINGS, IS_NEW_POSITION] AGGREGATOR_TOOLS = [CROSS_FUND_AGGREGATE] SYNTHESIZER_TOOLS = [POST_THEME_BRIEF_TO_SLACK] ``` ## Step 3: Define the Graph Workflow Nodes The shape is fan-out → fan-in. Each per-fund parser is a node that fetches the filing, parses the holdings table, looks up the fund profile, and diffs against the prior quarter. Multiple parsers run in parallel inside one GraphWorkflow when a filing covers multiple sub-funds under one umbrella manager. They converge into a Cross-Fund Aggregator, which feeds the Theme Synthesizer. Models are diversified across the DAG by the cognitive load of each node: * **Per-fund parsers** → `gpt-4.1-mini` — cheap, fast, mechanical. Most of the work is tool calling against structured XML. * **Cross-fund aggregator** → `gpt-4.1` — needs to reason over many per-fund summaries and group them coherently. * **Theme synthesizer** → `claude-sonnet-4.5` — produces the journalist-grade narrative the brief is built around. ```python theme={null} def build_13f_workflow_for_filing(cik: str, accession: str, fund_name: str, sub_funds: list[str]) -> dict: """ Build the GraphWorkflow payload for a single 13F filing. Graph structure: [Parser — sub-fund 1] ──┐ [Parser — sub-fund 2] ──┼──> [CrossFundAggregator] ──> [ThemeSynthesizer] [Parser — sub-fund N] ──┘ """ parser_agents = [ { "agent_name": f"Parser_{sub}", "description": f"Per-fund 13F parser for {sub}.", "system_prompt": ( "You are a 13F parser. Use the provided tools to: " "(1) fetch_13f_filing(cik, accession), " "(2) parse_13f_holdings on the raw text, " "(3) lookup_fund_profile(cik) for context, " "(4) diff_quarter_holdings against the prior quarter. " "Return a compact JSON object with: fund_name, strategy, " "top_5_adds, top_5_cuts, new_positions, eliminated_positions. " "Be terse — no prose." ), "model_name": "gpt-4.1-mini", "max_tokens": 3000, "temperature": 0.1, "max_loops": 1, "tools_list_dictionary": PARSER_TOOLS, } for sub in sub_funds ] aggregator_agent = { "agent_name": "CrossFundAggregator", "description": "Aggregates per-fund deltas into cross-fund sector flows.", "system_prompt": ( "You receive per-fund delta JSON from upstream parsers. " "Group adds and cuts by GICS sector, sum cumulative dollar flow per " "ticker, and call cross_fund_aggregate. Output a JSON object: " "{sector_adds, sector_cuts, top_inflows, top_outflows}. No prose." ), "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, "tools_list_dictionary": AGGREGATOR_TOOLS, } synthesizer_agent = { "agent_name": "ThemeSynthesizer", "description": "Produces the journalist-grade theme brief.", "system_prompt": ( "You are a senior markets editor. Given the aggregated cross-fund " "sector flows, produce a Markdown brief with: (1) top 10 sector adds " "with dollar magnitudes and named funds driving each, (2) top 10 " "sector cuts, (3) new positions crossing $100M of cumulative flow, " "(4) eliminated positions, (5) 3-5 emerging themes with named funds. " "Cite manager names. Be specific, numbers-forward, and printable." ), "model_name": "claude-sonnet-4.5", "max_tokens": 6000, "temperature": 0.4, "max_loops": 1, "tools_list_dictionary": SYNTHESIZER_TOOLS, } edges = ( [{"source": p["agent_name"], "target": "CrossFundAggregator"} for p in parser_agents] + [{"source": "CrossFundAggregator", "target": "ThemeSynthesizer"}] ) return { "name": f"13F-Tracker — {fund_name}", "description": f"Per-fund GraphWorkflow for {fund_name} ({cik}) filing {accession}.", "max_loops": 1, "task": ( f"Process the 13F-HR filing for {fund_name} (CIK {cik}, accession " f"{accession}). Parse all sub-fund holdings, diff against the prior " f"quarter, aggregate cross-fund flows, and produce the theme brief." ), "agents": parser_agents + [aggregator_agent, synthesizer_agent], "edges": edges, "entry_points": [p["agent_name"] for p in parser_agents], "end_points": ["ThemeSynthesizer"], } ``` ## Step 4: Run One Fund's 13F Smoke-test the shape against a single filing before you fire the burst. Pershing Square's umbrella files include the main fund plus the SPARC vehicle, which makes for a clean multi-parser fan-in. ```python theme={null} def run_single_filing(cik: str, accession: str, fund_name: str, sub_funds: list[str]) -> dict: payload = build_13f_workflow_for_filing(cik, accession, fund_name, sub_funds) response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() result = run_single_filing( cik="0001336528", accession="0001172661-24-000123", fund_name="Pershing Square Capital", sub_funds=["PSCM_Main", "PSCM_SPARC"], ) for node, output in result.get("outputs", {}).items(): print("=" * 60) print(f"[{node}]") print("=" * 60) if isinstance(output, list): output = " ".join(str(o) for o in output) print(str(output)[:600]) print(f"\nToken cost: {result['usage']['token_cost']:.4f} credits") print(f"Status: {result['status']}") ``` The ThemeSynthesizer output for a single filing is just that one manager's contribution to the cross-fund picture. The real value emerges when you batch it across the full 5,000-fund universe in Step 5 — at that point the aggregator sees the entire flow and the themes pop. ## Step 5: The Quarterly Burst — 5,000 Funds in One Night Production shape: you have a feed (EDGAR's RSS or a vendor like SEC-API.io) emitting accession numbers as they hit the system. You buffer them across the 48-hour deadline window, then fire one batch at 11pm Pacific on day 1 of the burst. ```python theme={null} # Imagine this list comes from a pull of EDGAR's 13F-HR daily index for the # deadline week. ~5,000 entries in practice. QUARTERLY_FILINGS = [ {"cik": "0001336528", "accession": "0001172661-24-000123", "fund_name": "Pershing Square Capital", "sub_funds": ["PSCM_Main"]}, {"cik": "0001478912", "accession": "0001478912-24-000089", "fund_name": "Tiger Global Management", "sub_funds": ["TGM_Main", "TGM_PIPE"]}, {"cik": "0001423053", "accession": "0001423053-24-000045", "fund_name": "Coatue Management", "sub_funds": ["Coatue_LP"]}, {"cik": "0001067983", "accession": "0001067983-24-000018", "fund_name": "Berkshire Hathaway", "sub_funds": ["BRK_Core"]}, # ... ~5,000 entries pulled from the EDGAR 13F-HR daily index ] def _run_one_filing(filing: dict) -> dict: payload = build_13f_workflow_for_filing( cik=filing["cik"], accession=filing["accession"], fund_name=filing["fund_name"], sub_funds=filing["sub_funds"], ) response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() def run_quarterly_burst(filings: list[dict], max_workers: int = 50) -> list[dict]: """ There is no bulk endpoint for graph workflows, so the burst is a pool of concurrent single calls to /v1/graph-workflow/completions rather than one request carrying the whole list. Tune max_workers against your account's concurrency and rate limits — see /v1/rate/limits. """ print(f"Dispatching burst of {len(filings)} GraphWorkflows across {max_workers} workers.") results: list[dict] = [] with ThreadPoolExecutor(max_workers=max_workers) as pool: futures = {pool.submit(_run_one_filing, f): f for f in filings} for future in as_completed(futures): filing = futures[future] try: results.append(future.result()) except requests.HTTPError as exc: results.append({"error": str(exc), "cik": filing["cik"], "accession": filing["accession"]}) return results results = run_quarterly_burst(QUARTERLY_FILINGS) # Persist raw responses first — partial network failures are easier to recover # from when you have the bytes on disk. out_dir = Path("13f_runs") / datetime.utcnow().strftime("%Y-Q%m-%d") out_dir.mkdir(parents=True, exist_ok=True) (out_dir / "raw_batch_response.json").write_text(json.dumps(results, indent=2)) ``` **The math.** A single 5-node GraphWorkflow per filing — three lean parsers on `gpt-4.1-mini`, one aggregator on `gpt-4.1`, one synthesizer on `claude-sonnet-4.5` — comes out to roughly **\$0.04 per filing under night-mode pricing**. Across the full quarterly burst: | Volume | Per-filing cost (night-mode) | Total | | --------------------------------------- | ---------------------------- | ----------- | | 5,000 13F-HR filings | \~\$0.04 | **\~\$200** | | With the night-mode 50% discount window | \~\$0.02 | **\~\$100** | A takeout dinner gets you the entire quarter's 13F coverage. Run four times a year and your annual budget for the program is roughly **\$400** in API cost. The burst must land inside the night-mode window (8pm–6am Pacific) to hit the headline pricing. Read the [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) guide for the schedule mechanics and how to chunk a larger batch across multiple windows if you exceed the rate ceiling. ## Step 6: The Theme Synthesizer Output A representative ThemeSynthesizer output for the cross-fund aggregate. This is the artifact your DB, Slack channel, and morning newsletter pull from. ```markdown theme={null} # 13F Tracker — Q3 2024 Cross-Fund Brief Reporting universe: 4,983 13F-HR filings, $6.4T in long US-equity AUM. ## Top 10 Sector Adds (by cumulative net dollar inflow) | Rank | Sector | Cumulative Net Add | Named Managers Driving | | ---- | ----------------------- | ------------------ | ---------------------- | | 1 | Semiconductors | +$18.4B | Coatue, Tiger Global, Lone Pine, Whale Rock | | 2 | Hyperscaler infra | +$12.1B | Pershing Square, ValueAct, Pat Dorsey | | 3 | Power & utilities | +$ 9.7B | Berkshire, Soros, Third Point | | 4 | Defense primes | +$ 6.2B | Discovery Capital, Maverick, Viking | | 5 | Obesity-adjacent biotech| +$ 5.9B | Baker Bros, Perceptive, RTW | | ... | ... | ... | ... | ## Top 10 Sector Cuts (by cumulative net dollar outflow) | Rank | Sector | Cumulative Net Cut | Named Managers Driving | | ---- | ----------------------- | ------------------ | ---------------------- | | 1 | Regional banks | -$ 8.7B | Hound Partners, Greenlight, Pershing Square | | 2 | China ADRs | -$ 7.4B | Tiger Global, Coatue, Lone Pine | | 3 | Legacy media | -$ 4.1B | Third Point, Trian, ValueAct | | ... | ... | ... | ... | ## New Positions Crossing $100M Cumulative Flow - **VST** (Vistra) — 14 funds initiated, $1.9B cumulative; Berkshire, Soros, Third Point - **CRWV** (CoreWeave) — 9 funds initiated, $640M cumulative; Coatue, Tiger Global, Whale Rock - **VRT** (Vertiv) — 11 funds initiated, $480M cumulative; Pershing Square, Lone Pine - **SMCI** (Super Micro) — 7 funds initiated, $310M cumulative; Maverick, Discovery ## Eliminated Positions - **PYPL** — 22 funds eliminated, $2.1B exiting; concentrated in long-short pods - **BABA** — 18 funds eliminated, $1.6B exiting; Tiger Global, Lone Pine, Hound - **CVS** — 12 funds eliminated, $740M exiting; ValueAct, Glenview ## Emerging Themes 1. **Power buildout as the AI shadow trade.** Power & utilities (+$9.7B) plus hyperscaler infra (+$12.1B) reads as one trade: capacity to feed the datacenter buildout. Berkshire (VST), Third Point (CEG), and Soros (NRG) are the names to watch. 2. **Semis are crowding.** Coatue, Tiger, Lone Pine, and Whale Rock are all adding the same five names (NVDA, AVGO, AMD, TSM, MRVL). When the velocity tightens like this, the unwind is fast — flag for the desk. 3. **China ADR capitulation.** -$7.4B cut concentrated in BABA, JD, PDD across the long-only crossover managers. The cleanup is finally happening. 4. **Obesity drugs broadening.** Baker, Perceptive, and RTW added second-tier names (VKTX, ALT, STRC) alongside their existing LLY/NVO core — signaling conviction that the platform is bigger than two names. 5. **Defense primes rotation.** Discovery and Maverick added LMT, NOC, GD simultaneously — the same week as the supplemental funding bill passed. ``` The Slack post fires automatically via the `post_theme_brief_to_slack` tool. The structured per-manager output also writes to a Postgres table so the desk can query "every fund that added NVDA this quarter, ranked by dollar size." ## Real Cost vs. Newsroom 13F Team | Approach | Wall time | Cost per quarter | Annualized | | -------------------------------------------------------------------- | ------------------------ | ------------------------------------- | ------------------------ | | Junior research analyst manually pulling \~50 "name brand" 13Fs | \~2 weeks of nights | — | \~\$120,000 fully loaded | | Senior markets editor reviewing and writing the brief under deadline | \~3 days each quarter | — | \~\$200,000 fully loaded | | Combined 2-person desk (junior + senior) covering \~50 funds | \~2 weeks | \~\$10,000–\$20,000 in burdened labor | \~\$320,000+ | | **GraphWorkflow batch burst, 5,000 funds, night-mode** | **\~1 hour server-side** | **\~\$100** | **\~\$400** | The swarm isn't replacing the senior editor — it's replacing the two weeks of mechanical 13F-pulling that buries them. The editor now lands at their desk on day 2 of the window with the entire universe of 4,983 filings already parsed, diffed, and themed. Their job becomes choosing which three themes to lead with — the work that actually requires judgement. ## Next Steps * [SEC Filing Triage Pipeline](/docs/examples/examples/sec-filing-triage-pipeline) for the same fan-out pattern applied to 8-K, S-1, and 10-K firehoses * [Insider Form 4 Monitor](/docs/examples/examples/insider-form4-monitor) for the daily-burst variant: insider transactions instead of quarterly positions * [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) for the DAG-shape reference and conditional gating patterns * [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) to schedule the burst against the discount window # Get Credit Balance Source: https://docs.swarms.ai/docs/examples/examples/account-credits Retrieve your current API credit balance including regular, free, and referral credits Retrieve your current API credit balance from the `/v1/account/credits` endpoint. This endpoint provides detailed information about all credit types associated with your account, including regular credits, free credits, referral credits, and the total available balance. Credits are automatically deducted after each API request completes. Free credits are used first, followed by regular credits. Check your balance regularly to ensure you have sufficient credits for your operations. ## Quick Start ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def get_credit_balance() -> dict | None: """Fetch current credit balance for the authenticated user.""" resp = requests.get(f"{BASE_URL}/v1/account/credits", headers=headers) if resp.status_code == 200: return resp.json() print(f"Error: {resp.status_code} - {resp.text}") return None if __name__ == "__main__": data = get_credit_balance() if data: print("✅ Credit balance retrieved successfully!") print(f"Total Credits: ${data.get('total_credits', 0):.2f}") print(f"Regular Credits: ${data.get('credit', 0):.2f}") print(f"Free Credits: ${data.get('free_credit', 0):.2f}") print(f"Referral Credits: ${data.get('referral_credits', 0):.2f}") print(json.dumps(data, indent=2)) ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getCreditBalance() { try { const response = await fetch(`${BASE_URL}/v1/account/credits`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Credit balance retrieved successfully!"); console.log(`Total Credits: $${data.total_credits?.toFixed(2) || 0}`); console.log(`Regular Credits: $${data.credit?.toFixed(2) || 0}`); console.log(`Free Credits: $${data.free_credit?.toFixed(2) || 0}`); console.log(`Referral Credits: $${data.referral_credits?.toFixed(2) || 0}`); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error("Error fetching credit balance:", error); return null; } } getCreditBalance(); ``` ```typescript theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } interface CreditBalance { credit: number free_credit: number referral_credits: number total_credits: number } async function getCreditBalance(): Promise { const res = await fetch(`${BASE_URL}/v1/account/credits`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, }) if (!res.ok) { const text = await res.text() throw new Error(`HTTP ${res.status}: ${text}`) } const data = (await res.json()) as CreditBalance console.log('✅ Credit balance retrieved successfully!') console.log(`Total Credits: $${data.total_credits.toFixed(2)}`) console.log(`Regular Credits: $${data.credit.toFixed(2)}`) console.log(`Free Credits: $${data.free_credit.toFixed(2)}`) console.log(`Referral Credits: $${data.referral_credits.toFixed(2)}`) return data } void getCreditBalance().catch(console.error) ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct CreditBalance { credit: f64, free_credit: f64, referral_credits: f64, total_credits: f64, } fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY") .expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let response = client .get("https://api.swarms.world/v1/account/credits") .header("x-api-key", api_key) .header("Content-Type", "application/json") .send()?; let balance: CreditBalance = response.json()?; println!("✅ Credit balance retrieved successfully!"); println!("Total Credits: ${:.2}", balance.total_credits); println!("Regular Credits: ${:.2}", balance.credit); println!("Free Credits: ${:.2}", balance.free_credit); println!("Referral Credits: ${:.2}", balance.referral_credits); Ok(()) } ``` ```go theme={null} package main import ( "encoding/json" "fmt" "io" "net/http" "os" ) type CreditBalance struct { Credit float64 `json:"credit"` FreeCredit float64 `json:"free_credit"` ReferralCredits float64 `json:"referral_credits"` TotalCredits float64 `json:"total_credits"` } func main() { apiKey := os.Getenv("SWARMS_API_KEY") if apiKey == "" { panic("SWARMS_API_KEY environment variable is required") } req, err := http.NewRequest("GET", "https://api.swarms.world/v1/account/credits", nil) if err != nil { panic(err) } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { panic(err) } var balance CreditBalance if err := json.Unmarshal(body, &balance); err != nil { panic(err) } fmt.Println("✅ Credit balance retrieved successfully!") fmt.Printf("Total Credits: $%.2f\n", balance.TotalCredits) fmt.Printf("Regular Credits: $%.2f\n", balance.Credit) fmt.Printf("Free Credits: $%.2f\n", balance.FreeCredit) fmt.Printf("Referral Credits: $%.2f\n", balance.ReferralCredits) } ``` ## Response Schema ### CreditBalanceOutput Object | Field | Type | Description | | ------------------ | -------- | ---------------------------------------------------- | | `credit` | `number` | Regular credit balance (purchased credits) | | `free_credit` | `number` | Free credit balance (promotional or welcome credits) | | `referral_credits` | `number` | Credits earned through the referral program | | `total_credits` | `number` | Total available credits (sum of all credit types) | ### Example Response ```json theme={null} { "credit": 50.00, "free_credit": 20.00, "referral_credits": 5.00, "total_credits": 75.00 } ``` ## Credit Usage Order Credits are deducted in the following order: 1. **Free Credits** - Used first for all API operations 2. **Regular Credits** - Used once free credits are exhausted (purchased and referral credits are combined into this balance) This ensures you maximize the value of free credits before drawing down your paid balance. ## Use Cases ### Monitor Credit Balance Check your credit balance before running large batch operations: ```python theme={null} def check_balance_before_batch(): balance = get_credit_balance() if balance and balance['total_credits'] < 10.00: print("⚠️ Low credit balance. Consider adding credits before running batch operations.") return False return True if check_balance_before_batch(): # Run batch operations pass ``` ### Track Credit Consumption Monitor credit usage over time: ```python theme={null} import time from datetime import datetime def track_credits(duration_minutes=60, interval_seconds=300): """Track credit balance over time.""" end_time = time.time() + (duration_minutes * 60) while time.time() < end_time: balance = get_credit_balance() if balance: timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] Total Credits: ${balance['total_credits']:.2f}") time.sleep(interval_seconds) ``` ## Best Practices 1. **Regular Monitoring**: Check your credit balance regularly, especially before large operations 2. **Low Balance Alerts**: Set up alerts when credits fall below a threshold 3. **Credit Types**: Understand which credit types you're using to optimize spending 4. **Referral Program**: Earn additional credits by referring new users ## Related Documentation * [Pricing Details](/docs/examples/examples/pricing-details-basic) - Understand API costs * [Pricing Cost Estimator](/docs/examples/examples/pricing-cost-estimator) - Estimate costs before running jobs * [Rate Limits](/docs/examples/api_examples/rate_limits) - Check rate limit status * [Account Management](https://swarms.world/platform/account) - Manage your account and add credits # Agent Handoffs Example Source: https://docs.swarms.ai/docs/examples/examples/agent-handoffs Build agents that delegate tasks to specialized handoff agents for focused expertise ## Customer Support Escalation with Handoffs This example demonstrates how to configure an agent with handoff agents — pre-defined specialist agents that the main agent can delegate to when a task requires specific expertise. ### What This Example Shows * Defining handoff agents inline within the `agent_config` * How the main agent decides when to hand off to a specialist * Nested agent specifications with independent configurations * Using handoffs through the `/v1/agent/completions` endpoint ### How Handoffs Work Unlike [sub-agent delegation](/docs/examples/examples/sub-agent-delegation) where agents are created dynamically at runtime, handoffs are **pre-defined** in your request. You specify the specialist agents upfront, and the main agent can route tasks to them as needed. ```mermaid theme={null} flowchart TD A[Task Received] --> B[Main Agent] B --> C{Needs specialist?} C -- No --> D[Main Agent Responds] C -- Yes --> E[Hand Off to Specialist] E --> F[Specialist Agent Responds] F --> B ``` ### Step 1: Setup ```python theme={null} import requests import os import json API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define the Agent with Handoffs The main agent gets a `handoffs` array containing fully configured specialist agents: ```python theme={null} def run_support_agent(customer_query: str) -> dict: """Route a customer query through a support agent with specialist handoffs.""" payload = { "agent_config": { "agent_name": "Support-Triage-Agent", "description": "Front-line customer support agent that triages and routes queries", "system_prompt": ( "You are a customer support triage agent. Assess each query and either:\n" "- Answer directly if it's a simple question\n" "- Hand off to Billing-Specialist for payment, invoicing, or subscription issues\n" "- Hand off to Technical-Support-Agent for bugs, errors, or integration problems\n" "- Hand off to Account-Manager for upgrades, cancellations, or enterprise inquiries\n\n" "Always acknowledge the customer's issue before routing." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, "handoffs": [ { "agent_name": "Billing-Specialist", "description": "Handles billing, payment, and subscription inquiries", "system_prompt": ( "You are a billing specialist. Help customers with:\n" "- Invoice questions and payment history\n" "- Subscription plan changes\n" "- Refund requests and credit adjustments\n" "- Payment method updates\n\n" "Be precise with amounts and dates. Always confirm changes before applying." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Technical-Support-Agent", "description": "Resolves technical issues, bugs, and integration problems", "system_prompt": ( "You are a technical support engineer. Help customers with:\n" "- API errors and debugging\n" "- Integration setup and configuration\n" "- Performance issues and troubleshooting\n" "- SDK and client library questions\n\n" "Ask for error messages and logs when needed. Provide step-by-step solutions." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Account-Manager", "description": "Handles account upgrades, cancellations, and enterprise requests", "system_prompt": ( "You are an account manager. Help customers with:\n" "- Plan upgrades and downgrades\n" "- Account cancellation and retention\n" "- Enterprise plan inquiries\n" "- Custom pricing and volume discounts\n\n" "Focus on understanding the customer's needs and offering the best solution." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "temperature": 0.3 } ] }, "task": customer_query } response = requests.post( f"{API_BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=120 ) return response.json() ``` ### Step 3: Run It ```python theme={null} # Technical issue — should hand off to Technical-Support-Agent result = run_support_agent( "I'm getting a 429 rate limit error when calling /v1/agent/completions. " "I'm on the free tier and only sending about 10 requests per minute. " "Can you help me debug this?" ) print(json.dumps(result, indent=2)) ``` **Expected Behavior:** 1. **Support-Triage-Agent** receives the query and identifies it as a technical issue 2. **Hands off** to Technical-Support-Agent 3. **Technical-Support-Agent** provides debugging steps for the rate limit error ### Step 4: Test Different Routes ```python theme={null} # Billing issue — should hand off to Billing-Specialist result = run_support_agent( "I was charged twice for my Pro subscription this month. " "Can I get a refund for the duplicate charge?" ) # Account inquiry — should hand off to Account-Manager result = run_support_agent( "We're a team of 50 engineers and want to upgrade to an enterprise plan. " "What volume pricing do you offer?" ) ``` Each handoff agent is a fully independent agent with its own model, system prompt, and configuration. The main agent decides which specialist to route to based on the task content. ## Next Steps * [Agent Completions Reference](/docs/documentation/capabilities/agent) — Full agent configuration parameters including `handoffs` * [Sub-Agent Delegation](/docs/examples/examples/sub-agent-delegation) — Dynamic agent creation at runtime (vs pre-defined handoffs) * [HierarchicalSwarm](/docs/documentation/multi-agent/hierarchical_swarm) — Multi-level agent coordination via the swarm endpoint # Single Agent Overview Source: https://docs.swarms.ai/docs/examples/examples/agent-overview Learn how to create and run single AI agents for specific tasks using the Swarms API. ## What This Example Shows * Creating a single agent with specific expertise * Configuring agent parameters (model, temperature, tokens) * Running agents with structured tasks * Handling agent responses and outputs Single agents are the building blocks of the Swarms API. Each agent can be configured with specific models, temperatures, and expertise areas. ## Quick Start ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv import json # Load environment variables load_dotenv() # Initialize the client client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) # Create and run a single agent result = client.agent.run( agent_config={ "agent_name": "Bloodwork Diagnosis Expert", "description": "An expert doctor specializing in interpreting and diagnosing blood work results.", "system_prompt": ( "You are an expert medical doctor specializing in the interpretation and diagnosis of blood work. " "Your expertise includes analyzing laboratory results, identifying abnormal values, " "explaining their clinical significance, and recommending next diagnostic or treatment steps. " "Provide clear, evidence-based explanations and consider differential diagnoses based on blood test findings." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5, }, task=( "A patient presents with the following blood work results: " "Hemoglobin: 10.2 g/dL (low), WBC: 13,000 /µL (high), Platelets: 180,000 /µL (normal), " "ALT: 65 U/L (high), AST: 70 U/L (high). " "Please provide a detailed interpretation, possible diagnoses, and recommended next steps." ), ) print(json.dumps(result, indent=4)) ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const payload = { agent_config: { agent_name: "Bloodwork Diagnosis Expert", description: "An expert doctor specializing in interpreting and diagnosing blood work results.", system_prompt: "You are an expert medical doctor specializing in the interpretation and diagnosis of blood work. Your expertise includes analyzing laboratory results, identifying abnormal values, explaining their clinical significance, and recommending next diagnostic or treatment steps.", model_name: "gpt-4.1", max_loops: 1, max_tokens: 1000, temperature: 0.5 }, task: "A patient presents with the following blood work results: Hemoglobin: 10.2 g/dL (low), WBC: 13,000 /µL (high), Platelets: 180,000 /µL (normal), ALT: 65 U/L (high), AST: 70 U/L (high). Please provide a detailed interpretation, possible diagnoses, and recommended next steps." }; fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { console.log("Agent Result:", JSON.stringify(data, null, 2)); }) .catch(error => console.error('Error:', error)); ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Bloodwork Diagnosis Expert", "description": "An expert doctor specializing in interpreting and diagnosing blood work results.", "system_prompt": "You are an expert medical doctor specializing in blood work interpretation.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5 }, "task": "A patient presents with blood work results: Hemoglobin 10.2 (low), WBC 13,000 (high), Platelets 180,000 (normal), ALT 65 (high), AST 70 (high). Please interpret and suggest diagnoses." }' ``` ## Agent Configuration Explained * **agent\_name**: A descriptive name for your agent * **description**: What the agent does * **system\_prompt**: The agent's expertise and behavior instructions * **model\_name**: The AI model to use (supports OpenAI, Anthropic, Groq, and more) * **max\_loops**: Maximum reasoning iterations (1 for single-pass tasks) * **max\_tokens**: Maximum response length * **temperature**: Creativity level (0.0 = focused, 1.0 = creative) ## Expected Output The agent will provide a structured medical analysis including: * Interpretation of each blood value * Possible diagnoses based on the results * Recommended next steps for the patient * Clinical context and significance ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Customization Ideas You can adapt this pattern for: * **Legal Analysis**: Contract review agents * **Code Review**: Software quality assurance agents * **Content Creation**: Writing and editing agents * **Data Analysis**: Business intelligence agents * **Customer Support**: FAQ and troubleshooting agents ## Next Steps After mastering single agents, explore: * Multi-agent swarms for complex workflows * Batch processing for multiple tasks * Agent chaining for sequential reasoning # Build an AI Hedge Fund Research Pipeline Source: https://docs.swarms.ai/docs/examples/examples/ai-hedge-fund A HierarchicalSwarm of a Portfolio Manager directing Fundamentals, Technicals, and Macro analysts — then scaled overnight across a full watchlist with batch completions. ## What This Example Shows * A `HierarchicalSwarm` with a Portfolio Manager (director) coordinating three worker analysts: Fundamentals, Technicals, and Macro * How to produce a structured buy/sell/hold call with a key signal for a single ticker * How to scale the same swarm across a 20-ticker watchlist using `/v1/swarm/batch/completions` * A realistic cost comparison against staffing a junior analyst team This tutorial uses `HierarchicalSwarm` and `/v1/swarm/batch/completions` — both included in every paid Swarms tier. For overnight batch jobs across hundreds of tickers, upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account) for higher rate limits and parallel execution. ## Why This Matters Most discretionary research desks are bottlenecked by the same thing: one analyst, one ticker at a time. A small fund's morning meeting touches maybe five names. By 9:30 AM half the watchlist has already moved without coverage. The job here is not to replace the PM's judgement — it is to put a structured, repeatable research note in front of them for every ticker on the watchlist before the open, every day. That is exactly what a hierarchical swarm of specialist analysts does cheaply and on a schedule. ## Step 1: Setup Install the dependencies and grab your API key from [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Analyst Team The Portfolio Manager owns the final call. Each analyst owns a single lens — fundamentals, technicals, or macro — and writes a tight brief the PM can act on. ```python theme={null} PORTFOLIO_MANAGER_PROMPT = ( "You are a Portfolio Manager at a long/short equity hedge fund. " "Review the briefs from your Fundamentals, Technicals, and Macro analysts. " "Issue a single decision in this exact format:\n\n" "TICKER: \n" "CALL: \n" "CONVICTION: \n" "KEY SIGNAL: \n" "RISK: \n\n" "Be decisive. Do not hedge across all three analysts — pick the dominant signal." ) FUNDAMENTALS_PROMPT = ( "You are a Fundamental Equity Analyst. Given a ticker, write a brief covering: " "revenue growth trajectory, margin profile, FCF generation, balance sheet health, " "and the single most important catalyst over the next two quarters. " "Keep it under 200 words. Be specific." ) TECHNICALS_PROMPT = ( "You are a Technical Analyst. Given a ticker, write a brief covering: " "current trend regime, key support and resistance levels, momentum indicators " "(RSI, MACD), volume profile, and a near-term target with stop. " "Keep it under 200 words. Be specific." ) MACRO_PROMPT = ( "You are a Macro Analyst. Given a ticker, write a brief covering: " "sector positioning vs. the current rate regime, FX and commodity sensitivities, " "policy and regulatory tailwinds or headwinds, and how the name behaves in a " "risk-off rotation. Keep it under 200 words. Be specific." ) def build_swarm_for_ticker(ticker: str) -> dict: return { "name": f"AI Hedge Fund Research — {ticker}", "description": "Portfolio Manager directing Fundamentals, Technicals, and Macro analysts.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( f"Produce a same-day research note for {ticker}. " f"Each analyst writes their brief, then the Portfolio Manager issues a final call." ), "agents": [ { "agent_name": "Portfolio Manager", "description": "Director — synthesizes analyst briefs into a single call.", "system_prompt": PORTFOLIO_MANAGER_PROMPT, "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, }, { "agent_name": "Fundamentals Analyst", "description": "Earnings, margins, balance sheet, catalysts.", "system_prompt": FUNDAMENTALS_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, { "agent_name": "Technicals Analyst", "description": "Trend, levels, momentum, volume.", "system_prompt": TECHNICALS_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, { "agent_name": "Macro Analyst", "description": "Rates, FX, commodities, policy.", "system_prompt": MACRO_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, ], } ``` ## Step 3: Run One Ticker End-to-End Start with a single name — this is the loop you will scale. ```python theme={null} def run_single_ticker(ticker: str) -> dict: payload = build_swarm_for_ticker(ticker) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() result = run_single_ticker("NVDA") for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600]) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` The Portfolio Manager's final output is the one you persist to your research database. The three analyst briefs are the audit trail that justifies the call — every PM signoff is fully reproducible from the inputs. ## Step 4: Scale Across the Watchlist with Batch Completions For overnight research notes across an entire watchlist, send every ticker as one payload to `/v1/swarm/batch/completions`. The API executes the swarms in parallel and returns a list of results. ```python theme={null} WATCHLIST = [ "NVDA", "AAPL", "MSFT", "GOOGL", "META", "AMZN", "TSLA", "AMD", "AVGO", "CRM", "ORCL", "ADBE", "NFLX", "PYPL", "SHOP", "UBER", "COIN", "PLTR", "SNOW", "DDOG", ] def run_watchlist_batch(tickers: list[str]) -> list[dict]: payload = [build_swarm_for_ticker(t) for t in tickers] response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload, timeout=900, ) response.raise_for_status() return response.json() results = run_watchlist_batch(WATCHLIST) with open("morning_notes.jsonl", "w") as f: for ticker, result in zip(WATCHLIST, results): # Extract the Portfolio Manager's final call. Batch items are shaped # {"status", "swarm_name", "result", "usage"} — the conversation lives # under "result", not "output". pm_call = next( (o["content"] for o in result.get("result", []) if "Portfolio Manager" in o.get("role", "")), "", ) if isinstance(pm_call, list): pm_call = " ".join(str(c) for c in pm_call) f.write(json.dumps({"ticker": ticker, "call": pm_call}) + "\n") total_cost = sum(r.get("usage", {}).get("billing_info", {}).get("total_cost", 0) for r in results) print(f"Generated {len(results)} morning notes for ${total_cost:.2f}") ``` Schedule this script as a cron job for 6:00 AM ET on weekdays. By the time the PM sits down with coffee, `morning_notes.jsonl` has a structured call for every ticker on the watchlist — with the analyst briefs sitting in the full response for any name they want to drill into. ## Real Cost vs. Human Analyst | Scenario | Cost per ticker | Cost per day (20 tickers) | Annualized | | ----------------------------------------- | --------------- | ------------------------- | ---------- | | Hierarchical swarm (4 agents, GPT-4.1) | \~\$0.12 | \~\$2.40 | \~\$600 | | One junior analyst (fully loaded \$150k) | — | \~\$600 | \$150,000 | | Three-analyst pod (junior + mid + senior) | — | \~\$2,000 | \$500,000 | The swarm is not a replacement for your PM — it is a tireless research associate that runs every night so your humans can spend their time on the calls that actually matter. ## Next Steps * See [Claude Opus 4.8](/docs/examples/examples/claude-opus-4-8) to swap in Anthropic's strongest reasoning model for high-conviction names * Read the [ETF Analysis Grid](/docs/examples/examples/etf-analysis-grid) for the fan-out × fan-out variant when you have multiple analyst lenses and multiple universes * Browse the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) for the director-and-workers pattern applied to software teams # Available Tools Source: https://docs.swarms.ai/docs/examples/examples/available-tools Discover and explore all available tools supported by the Swarms API Get a comprehensive list of all tools available through the Swarms API. The `/v1/tools/available` endpoint provides information about integrated tools and capabilities that can enhance your agents and swarms. Tools extend agent capabilities by providing access to external services, APIs, databases, and specialized functions. ## Quick Start ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } def get_available_tools(): """Get all available tools""" response = requests.get( f"{BASE_URL}/v1/tools/available", headers=headers ) if response.status_code == 200: return response.json() else: print(f"Error: {response.status_code} - {response.text}") return None # Get available tools tools_data = get_available_tools() if tools_data: print("✅ Available tools retrieved successfully!") print(json.dumps(tools_data, indent=2)) ``` ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getAvailableTools() { try { const response = await fetch(`${BASE_URL}/v1/tools/available`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Available tools retrieved successfully!"); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error('Error:', error); return null; } } // Get available tools getAvailableTools(); ``` ```bash theme={null} # Get available tools curl -X GET "https://api.swarms.world/v1/tools/available" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" # Example response: # { # "status": "success", # "tools": [ # "auto_search", # "web_scraper" # ] # } ``` ## Tool Integration Enable a tool on an agent by adding its name to the top-level `tools_enabled` field of the request (alongside `agent_config` and `task`). Both tools can be enabled in the same request — each name present in `tools_enabled` adds its tool to the agent. ```python theme={null} payload = { "agent_config": { "agent_name": "Research Assistant", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "Find the latest developments in quantum computing and summarize the key breakthroughs.", "tools_enabled": ["auto_search"] } ``` ```python theme={null} payload = { "agent_config": { "agent_name": "Document Analyst", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "Scrape and summarize the content at https://example.com/article.", "tools_enabled": ["web_scraper"] } ``` ## Tool Categories | Tool | Description | Billed As | | ------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------- | | `auto_search` | Web search powered by Exa, used to ground agent responses in current information | `agent-completions-tool-usage-exa-search` (per search) | | `web_scraper` | Fetches and formats the content of a URL for the agent to read | `agent-completions-tool-usage-web-scraper` (per scrape) | Search and scrape costs are billed per use — see [Pricing Details](/docs/examples/examples/pricing-details-basic) for current `search_cost` and `scrape_cost` rates. ## Best Practices ### Tool Selection 1. **Match Tools to Tasks**: Choose tools that best fit your specific use case 2. **Avoid Overloading**: Don't enable too many tools for a single agent 3. **Test Combinations**: Test tool combinations to ensure they work well together 4. **Monitor Performance**: Track how tools affect response time and cost ### Configuration 1. **Set Appropriate Limits**: Configure tool-specific limits and timeouts 2. **Handle Errors Gracefully**: Implement proper error handling for tool failures 3. **Cache Results**: Cache tool results when appropriate to improve performance 4. **Security First**: Ensure tools access only authorized resources ### Usage Optimization 1. **Batch Operations**: Use tools that support batch operations when possible 2. **Async Processing**: Leverage asynchronous tool execution for better performance 3. **Resource Management**: Monitor tool usage and resource consumption 4. **Cost Awareness**: Be aware of costs associated with tool usage # Batch Agent Completions at Scale Source: https://docs.swarms.ai/docs/examples/examples/batch-agent-scale-tutorial Score 10,000 sales leads or triage 10,000 support tickets in a single batch call. The throughput-and-cost story for /v1/agent/batch/completions. ## What This Example Shows * How to score or triage tens of thousands of records with `/v1/agent/batch/completions` * A real lead-scoring workload built on `/v1/agent/batch/completions` * Per-record cost math you can take to your CFO * How to chunk a large input list to stay inside the endpoint's hard batch-size limit, and how to submit those chunks concurrently so throughput doesn't collapse * Where this beats hand-rolled `asyncio.gather` against the single-agent endpoint **Premium-only endpoint.** `/v1/agent/batch/completions` is restricted to Pro, Ultra, and Premium subscribers. Free-tier keys will get a 403. [Upgrade your account](https://swarms.world/platform/account) to unlock high-throughput batch processing. ## Why This Matters Every revenue team has a backlog of records that need a human-quality judgment call: leads to qualify, tickets to triage, resumes to screen, transcripts to tag. Hiring a person to do this work costs \$30-\$60 per hour and produces 20-40 decisions per hour. Sending each row to a single-agent endpoint one-at-a-time gets you the right answer but burns wall-clock time and connection overhead. The batch endpoint compresses that same workload into one request, parallelized server-side, with a single bill at the end. This tutorial shows the concrete shape of that job. ## Step 1: Setup ```bash theme={null} pip install swarms-client python-dotenv ``` ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Define the Lead Scoring Agent We will use one agent definition and reuse it across every record. The agent reads a lead profile and returns a score and a one-line reason. ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} LEAD_SCORER_CONFIG = { "agent_name": "Lead Scoring Specialist", "description": "Scores inbound B2B sales leads on a 0-100 fit scale.", "system_prompt": ( "You are a senior B2B sales operations analyst. Given a lead profile, " "score the lead on a 0-100 scale based on ICP fit, buying intent, and " "budget signals. Respond as strict JSON: " '{"score": int, "tier": "A"|"B"|"C"|"D", "reason": "one sentence"}' ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 200, "temperature": 0.2, } ``` ## Step 3: Load Your Records In a real workload these come from a CRM export, a database query, or an S3 file. For this tutorial we generate a synthetic list of 10,000 leads. ```python theme={null} def build_lead_record(i: int) -> dict: return { "lead_id": f"L{i:05d}", "company": f"Acme Subsidiary {i}", "industry": ["fintech", "healthtech", "ecommerce", "logistics"][i % 4], "headcount": 50 + (i % 500), "title": ["VP Eng", "CTO", "Director of Data", "Head of Ops"][i % 4], "intent_signal": "downloaded whitepaper" if i % 3 == 0 else "visited pricing", } leads = [build_lead_record(i) for i in range(10_000)] ``` ## Step 4: Convert Records into Batch Requests Each item in the batch body is one `AgentCompletion`: the same `agent_config` plus a per-record `task`. ```python theme={null} def lead_to_batch_item(lead: dict) -> dict: task = ( f"Score this lead and return strict JSON.\n" f"Lead ID: {lead['lead_id']}\n" f"Company: {lead['company']}\n" f"Industry: {lead['industry']}\n" f"Headcount: {lead['headcount']}\n" f"Contact title: {lead['title']}\n" f"Intent signal: {lead['intent_signal']}" ) return {"agent_config": LEAD_SCORER_CONFIG, "task": task} batch_items = [lead_to_batch_item(lead) for lead in leads] ``` ## Step 5: Submit in Chunks `/v1/agent/batch/completions` enforces a **hard server-side cap of 50 items per request** — send more than 50 `AgentCompletion` objects in one call and you get back an HTTP 422 ("List should have at most 50 items after validation"). For 10,000 leads that means 200 chunked requests, so submit the chunks concurrently with a small thread pool instead of one at a time, or wall-clock time balloons. ```python theme={null} import concurrent.futures CHUNK_SIZE = 50 # hard cap enforced by the server; larger chunks return HTTP 422 def run_chunk(chunk: list[dict]) -> list[dict]: response = requests.post( f"{BASE_URL}/v1/agent/batch/completions", headers=headers, json=chunk, timeout=120, ) response.raise_for_status() # The endpoint returns an envelope, not a bare list: # {"batch_id", "total_requests", "results", "execution_time", "timestamp"} return response.json()["results"] chunks = [ batch_items[start : start + CHUNK_SIZE] for start in range(0, len(batch_items), CHUNK_SIZE) ] all_results: list[dict] = [] with concurrent.futures.ThreadPoolExecutor(max_workers=25) as executor: for chunk_results in executor.map(run_chunk, chunks): all_results.extend(chunk_results) print(f"Scored {len(all_results)} leads.") ``` Each request is capped at 50 items, but the server processes those 50 concurrently, and Pro/Ultra/Premium keys allow up to 2,000 requests per minute — so a pool of 20-30 worker threads submitting 50-item chunks in parallel gets you back to job-like throughput without tripping the per-request limit or the per-minute rate limit. ## Step 6: Aggregate and Route Parse each agent response, slot leads into A/B/C/D tiers, and forward only A-tier leads to your SDRs. ```python theme={null} tiers: dict[str, list[dict]] = {"A": [], "B": [], "C": [], "D": []} for lead, result in zip(leads, all_results): try: # The agent output is a JSON string inside the response envelope. output_text = result["outputs"][-1]["content"] if isinstance(result.get("outputs"), list) else result.get("output", "") parsed = json.loads(output_text) tier = parsed.get("tier", "D") tiers.setdefault(tier, []).append({**lead, **parsed}) except (json.JSONDecodeError, KeyError, TypeError): tiers["D"].append({**lead, "score": 0, "tier": "D", "reason": "parse_error"}) for tier, items in tiers.items(): print(f"Tier {tier}: {len(items)} leads") print("Top 5 A-tier leads:") for item in tiers["A"][:5]: print(f" {item['lead_id']} | {item['company']} | {item['reason']}") ``` The exact response shape depends on the model and whether the agent returns structured outputs. Wrap the JSON parse in a try/except and dump unparseable rows to a review queue — never let one bad row halt a 10k-lead pipeline. ## The Cost Math Pricing varies by model and current token rates — these numbers are illustrative, not a quote. | Approach | Wall time | Direct cost | Burdened cost | | ------------------------------------------------------------ | ------------------- | ------------------- | --------------------------- | | Human SDR scoring 10,000 leads | \~400 hours | \$20,000 at \$50/hr | \$30,000+ with overhead | | Single-agent endpoint, sequential | \~6 hours | \~\$30 | \$30 + 6 hours of your time | | **Batch endpoint, 200 chunks of 50 (25 concurrent workers)** | **\~15-25 minutes** | **\~\$30** | **\$30 + 15-25 minutes** | **This batch costs roughly \$25-\$35 to run on gpt-4.1 with short outputs. A human SDR team would take \~400 hours at \$50/hour to produce the same triage — about \$20,000 in direct labor.** Run the same job nightly and you have replaced a full-time research desk with a recurring cron and an API key. ## Adapting the Pattern Swap the `agent_config` system prompt and the per-record `task` shape to retarget: | Workload | System prompt focus | Per-record task | | -------------------------------- | ------------------------------------ | ---------------------------- | | **Support ticket triage** | severity + category + suggested team | ticket body + customer tier | | **Resume screening** | match-to-role score + flags | resume text + JD summary | | **Transcript tagging** | topic labels + sentiment | transcript window | | **Compliance review** | policy violations + risk | document chunk + policy list | | **Product review summarization** | sentiment + key claims | review text + product SKU | Nothing else in this tutorial changes — same endpoint, same chunking, same cost-tracking story. ## Next Steps * [Batch Swarm Completions for Overnight Reports](/docs/examples/examples/batch-swarm-scale-tutorial) when one agent isn't enough per record * [Batch Agent Completions (Single Agent)](/docs/examples/examples/batch-processing) for the request-shape mechanics * [Streaming](/docs/examples/examples/streaming) when you need real-time token output instead of batch throughput # Batch Agent Completions (Single Agent) Source: https://docs.swarms.ai/docs/examples/examples/batch-processing Process multiple single-agent tasks efficiently in parallel using the /v1/agent/batch/completions endpoint. **Premium Tier Required**: The `/v1/agent/batch/completions` endpoint is restricted to Pro, Ultra, and Premium plan subscribers. Free tier users will receive a 403 error. [Upgrade your account](https://swarms.world/platform/account) to access batch processing capabilities. **Single Agent vs Multi-Agent**: This example covers batch processing for **single agents** (`/v1/agent/batch/completions`). For batching **multi-agent swarms**, see [Batch Swarm Completions (Multi-Agent)](/docs/examples/examples/batch-swarm-completions). **Batch size limit**: A single request to `/v1/agent/batch/completions` accepts at most **50** `AgentCompletion` items. Requests with more than 50 items are rejected with an HTTP 422 validation error. To process larger volumes, split your work into chunks of 50 and submit multiple requests — see [Batch Agent Completions at Scale](/docs/examples/examples/batch-agent-scale-tutorial) for a chunking pattern. ## What This Example Shows * Processing multiple agent tasks in a single request * Configuring different agents for different types of analysis * Efficient batch execution for multiple related tasks * Handling diverse task types with specialized agents ## Quick Start ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define multiple batch requests (array of AgentCompletion) batch_requests = [ { "agent_config": { "agent_name": "Bloodwork Diagnosis Expert", "description": "Expert in blood work interpretation.", "system_prompt": ( "You are a doctor who interprets blood work. Give concise, clear explanations and possible diagnoses." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5, }, "task": ( "Blood work: Hemoglobin 10.2 (low), WBC 13,000 (high), Platelets 180,000 (normal), " "ALT 65 (high), AST 70 (high). Interpret and suggest diagnoses." ), }, { "agent_config": { "agent_name": "Radiology Report Summarizer", "description": "Expert in summarizing radiology reports.", "system_prompt": ( "You are a radiologist. Summarize the findings of radiology reports in clear, patient-friendly language." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5, }, "task": ( "Radiology report: Chest X-ray shows mild cardiomegaly, no infiltrates, no effusion. Summarize the findings." ), }, ] def run_agent_batch_completions(): response = requests.post( f"{BASE_URL}/v1/agent/batch/completions", headers=headers, json=batch_requests, timeout=600, ) response.raise_for_status() return response.json() if __name__ == "__main__": result = run_agent_batch_completions() print(json.dumps(result, indent=4)) ``` ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } type AgentSpec = { agent_name?: string description?: string system_prompt?: string model_name?: string max_loops?: number | string max_tokens?: number temperature?: number } type AgentCompletion = { agent_config: AgentSpec task?: string } async function runAgentBatchCompletions(): Promise { const batchPayload: AgentCompletion[] = [ { agent_config: { agent_name: 'Bloodwork Diagnosis Expert', description: 'Expert in blood work interpretation.', system_prompt: 'You are a doctor who interprets blood work. Give concise, clear explanations and possible diagnoses.', model_name: 'gpt-4.1', max_loops: 1, max_tokens: 1000, temperature: 0.5, }, task: 'Blood work: Hemoglobin 10.2 (low), WBC 13,000 (high), Platelets 180,000 (normal), ALT 65 (high), AST 70 (high). Interpret and suggest diagnoses.', }, { agent_config: { agent_name: 'Radiology Report Summarizer', description: 'Expert in summarizing radiology reports.', system_prompt: 'You are a radiologist. Summarize the findings of radiology reports in clear, patient-friendly language.', model_name: 'gpt-4.1', max_loops: 1, max_tokens: 1000, temperature: 0.5, }, task: 'Radiology report: Chest X-ray shows mild cardiomegaly, no infiltrates, no effusion. Summarize the findings.', }, ] const res = await fetch(`${BASE_URL}/v1/agent/batch/completions`, { method: 'POST', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify(batchPayload), }) if (!res.ok) { const text = await res.text() throw new Error(`HTTP ${res.status}: ${text}`) } return (await res.json()) as unknown } void runAgentBatchCompletions() .then((result) => { console.log('Batch Results:', JSON.stringify(result, null, 2)) }) .catch(console.error) ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let batch_payload = json!([ { "agent_config": { "agent_name": "Bloodwork Diagnosis Expert", "description": "Expert in blood work interpretation.", "system_prompt": "You are a doctor who interprets blood work. Give concise, clear explanations and possible diagnoses.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5 }, "task": "Blood work: Hemoglobin 10.2 (low), WBC 13,000 (high), Platelets 180,000 (normal), ALT 65 (high), AST 70 (high). Interpret and suggest diagnoses." }, { "agent_config": { "agent_name": "Radiology Report Summarizer", "description": "Expert in summarizing radiology reports.", "system_prompt": "You are a radiologist. Summarize the findings of radiology reports in clear, patient-friendly language.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1000, "temperature": 0.5 }, "task": "Radiology report: Chest X-ray shows mild cardiomegaly, no infiltrates, no effusion. Summarize the findings." } ]); let res = client .post("https://api.swarms.world/v1/agent/batch/completions") .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&batch_payload) .send()?; res.error_for_status_ref()?; let body = res.text()?; println!("{body}"); Ok(()) } ``` ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/batch/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '[ { "agent_config": { "agent_name": "Bloodwork Diagnosis Expert", "model_name": "gpt-4.1", "max_tokens": 1000, "temperature": 0.5 }, "task": "Blood work analysis..." }, { "agent_config": { "agent_name": "Radiology Report Summarizer", "model_name": "gpt-4.1", "max_tokens": 1000, "temperature": 0.5 }, "task": "Radiology report summary..." } ]' ``` ## Batch Processing Benefits * **Efficiency**: Process multiple tasks in parallel * **Cost Optimization**: Reduce API call overhead * **Consistency**: Apply similar processing across multiple items * **Scalability**: Handle large volumes of work efficiently ## Use Cases Batch processing is ideal for: * **Document Analysis**: Review multiple contracts, reports, or documents * **Data Processing**: Analyze large datasets with multiple perspectives * **Content Generation**: Create variations of content for different audiences * **Quality Assurance**: Review multiple code files, designs, or content pieces * **Customer Support**: Process multiple support tickets with specialized agents ## Expected Output The batch processor will return results for each task: * Bloodwork analysis with diagnosis and recommendations * Radiology report summary in patient-friendly language * Each result maintains the structure and quality of individual agent runs ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Advanced Batch Processing You can extend this pattern to: * **Dynamic Batching**: Group similar tasks automatically * **Priority Processing**: Assign importance levels to different tasks * **Result Aggregation**: Combine multiple results into unified insights * **Error Handling**: Gracefully handle failures in individual batch items ## Next Steps After mastering batch processing, explore: * Multi-agent swarms for complex collaborative workflows * Sequential workflows for dependent tasks * Concurrent workflows for parallel execution * Agent routing for intelligent task distribution # Batch Swarm Completions (Multi-Agent) Source: https://docs.swarms.ai/docs/examples/examples/batch-swarm-completions Execute multiple multi-agent swarm workflows in parallel using the /v1/swarm/batch/completions endpoint. **Premium Tier Required**: The /v1/swarm/batch/completions endpoint is restricted to Pro, Ultra, and Premium plan subscribers. Free tier users will receive a 403 error. See Premium Endpoints. **Multi-Agent vs Single Agent**: This example covers batch processing for **multi-agent swarms** (`/v1/swarm/batch/completions`). For batching **single agent tasks**, see [Batch Agent Completions (Single Agent)](/docs/examples/examples/batch-processing). Run many swarm jobs in a **single API call** using `/v1/swarm/batch/completions`.\ This is ideal for: * Evaluating the **same swarm configuration** across many tasks * Running **different swarm types** side‑by‑side * Large‑scale research, content generation, or analysis workloads All requests share the same **base URL**: ```text theme={null} https://api.swarms.world ``` ## Quick Start: Batch Swarm Completion Each item in the batch is a full `SwarmSpec` (the same structure used for `/v1/swarm/completions`). ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Define a couple of swarms to run in parallel batch_payload = [ { "name": "Market Analysis Swarm", "description": "Sequential research swarm for market analysis", "swarm_type": "SequentialWorkflow", "task": "Analyze 2025 AI agent market trends and key players.", "max_loops": 1, "agents": [ { "agent_name": "Research-Analyst", "description": "Collects and summarizes market information.", "system_prompt": "You are a senior market research analyst.", "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.4, } ], }, { "name": "Technical Review Swarm", "description": "Concurrent workflow for technical deep‑dives", "swarm_type": "ConcurrentWorkflow", "task": "Compare Rust and TypeScript for backend microservices.", "max_loops": 1, "agents": [ { "agent_name": "Rust-Expert", "description": "Analyzes Rust for backend services.", "system_prompt": "You are a senior Rust engineer.", "model_name": "gpt-4.1", "max_tokens": 1000, }, { "agent_name": "TypeScript-Expert", "description": "Analyzes TypeScript/Node.js for backend services.", "system_prompt": "You are a senior TypeScript backend engineer.", "model_name": "gpt-4.1", "max_tokens": 1000, }, ], }, ] def run_batch_swarm_completions(): response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=batch_payload, timeout=600, ) response.raise_for_status() return response.json() if __name__ == "__main__": results = run_batch_swarm_completions() print("✅ Batch swarm completions finished") print(json.dumps(results, indent=2)) ``` ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } type AgentSpec = { agent_name?: string description?: string system_prompt?: string model_name?: string max_tokens?: number temperature?: number max_loops?: number | string } type SwarmSpec = { name?: string description?: string swarm_type?: string task?: string max_loops?: number agents?: AgentSpec[] } async function runBatchSwarmCompletions(): Promise { const batchPayload: SwarmSpec[] = [ { name: 'Market Analysis Swarm', description: 'Sequential research swarm for market analysis', swarm_type: 'SequentialWorkflow', task: 'Analyze 2025 AI agent market trends and key players.', max_loops: 1, agents: [ { agent_name: 'Research-Analyst', description: 'Collects and summarizes market information.', system_prompt: 'You are a senior market research analyst.', model_name: 'gpt-4.1', max_tokens: 1500, temperature: 0.4, }, ], }, { name: 'Technical Review Swarm', description: 'Concurrent workflow for technical deep‑dives', swarm_type: 'ConcurrentWorkflow', task: 'Compare Rust and TypeScript for backend microservices.', max_loops: 1, agents: [ { agent_name: 'Rust-Expert', description: 'Analyzes Rust for backend services.', system_prompt: 'You are a senior Rust engineer.', model_name: 'gpt-4.1', max_tokens: 1000, }, { agent_name: 'TypeScript-Expert', description: 'Analyzes TypeScript/Node.js for backend services.', system_prompt: 'You are a senior TypeScript backend engineer.', model_name: 'gpt-4.1', max_tokens: 1000, }, ], }, ] const res = await fetch(`${BASE_URL}/v1/swarm/batch/completions`, { method: 'POST', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify(batchPayload), }) if (!res.ok) { const text = await res.text() throw new Error(`HTTP ${res.status}: ${text}`) } return (await res.json()) as unknown } void runBatchSwarmCompletions() .then((results) => { console.log('✅ Batch swarm completions finished') console.log(JSON.stringify(results, null, 2)) }) .catch(console.error) ``` ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let batch_payload = json!([ { "name": "Market Analysis Swarm", "description": "Sequential research swarm for market analysis", "swarm_type": "SequentialWorkflow", "task": "Analyze 2025 AI agent market trends and key players.", "max_loops": 1, "agents": [ { "agent_name": "Research-Analyst", "description": "Collects and summarizes market information.", "system_prompt": "You are a senior market research analyst.", "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.4 } ] }, { "name": "Technical Review Swarm", "description": "Concurrent workflow for technical deep-dives", "swarm_type": "ConcurrentWorkflow", "task": "Compare Rust and TypeScript for backend microservices.", "max_loops": 1, "agents": [ { "agent_name": "Rust-Expert", "description": "Analyzes Rust for backend services.", "system_prompt": "You are a senior Rust engineer.", "model_name": "gpt-4.1", "max_tokens": 1000 }, { "agent_name": "TypeScript-Expert", "description": "Analyzes TypeScript/Node.js for backend services.", "system_prompt": "You are a senior TypeScript backend engineer.", "model_name": "gpt-4.1", "max_tokens": 1000 } ] } ]); let res = client .post("https://api.swarms.world/v1/swarm/batch/completions") .header("x-api-key", api_key) .header("Content-Type", "application/json") .json(&batch_payload) .send()?; res.error_for_status_ref()?; let body = res.text()?; println!("{body}"); Ok(()) } ``` ## Interpreting the Response The endpoint returns an array of results, one per item in the batch, in the same order as the request. Each entry is leaner than the single-swarm `/v1/swarm/completions` response — there is no `job_id`, `swarm_type`, or `execution_time` field, and the swarm's output is under `result`, not `output`: ```json theme={null} [ { "status": "success", "swarm_name": "Market Analysis Swarm", "result": { "summary": "..." }, "usage": { "input_tokens": 8500, "output_tokens": 3200, "total_tokens": 11700, "billing_info": { "cost_breakdown": { "agent_cost": 0.01, "input_token_cost": 0.055, "output_token_cost": 0.0592, "token_counts": { "total_input_tokens": 8500, "total_output_tokens": 3200, "total_tokens": 11700 }, "num_agents": 1, "night_time_discount_applied": false }, "total_cost": 0.1242, "discount_active": false, "discount_type": "none", "discount_percentage": 0 } } } ] ``` If a swarm in the batch fails, its entry has `"status": "error"` and a `detail` message instead of `result`/`usage`: ```json theme={null} { "status": "error", "swarm_name": "Technical Review Swarm", "detail": "Failed to run swarm: ..." } ``` Use `swarm_name`, `status`, and `usage.billing_info.total_cost` for **auditing**, **cost tracking**, and **monitoring** across your batch workloads. Check each entry's `status` before reading `result` — a failed swarm does not raise an HTTP error for the whole batch, it just reports `"status": "error"` in its own slot. # Batch Swarm Completions for Overnight Reports Source: https://docs.swarms.ai/docs/examples/examples/batch-swarm-scale-tutorial Run 50 separate due-diligence swarms as one overnight batch job using /v1/swarm/batch/completions. The enterprise scheduling pattern. ## What This Example Shows * The enterprise pattern: kick off a long batch of independent multi-agent swarms at end-of-day, have results waiting at 7am * A real due-diligence workload across 50 portfolio companies * How to schedule with cron, persist results, and recover from partial failures * Concrete cost framing versus a human research desk * Why this is materially different from running each swarm one at a time **Premium-only endpoint.** `/v1/swarm/batch/completions` is restricted to Pro, Ultra, and Premium subscribers. Free-tier keys will get a 403. [Upgrade your account](https://swarms.world/platform/account) to unlock enterprise batch swarm execution. ## Why This Matters A single multi-agent swarm — director plus three specialists — does the work of an analyst team over a 30-minute call. But the real enterprise pattern isn't one swarm. It's *fifty* swarms running while everyone sleeps: one per portfolio company, one per RFP response, one per region for a market scan, one per candidate in a final-round panel. Schedule a batch swarm job at 8pm, have a folder of completed due-diligence memos waiting at 7am. This tutorial shows how to build that job. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Define a Reusable Due-Diligence Swarm Template Every swarm in the batch is a full `SwarmSpec`. We define one template (a four-agent `HierarchicalSwarm`) and stamp it out per company. ```python theme={null} import json import os from datetime import datetime from pathlib import Path import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} def due_diligence_swarm(company: str, ticker: str) -> dict: return { "name": f"Due Diligence - {company}", "description": f"Hierarchical due diligence swarm for {company} ({ticker}).", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( f"Produce a board-ready due diligence memo on {company} (ticker: {ticker}). " "Cover: business model, competitive moat, financial health, key risks, " "and a one-paragraph recommendation. Maximum 800 words." ), "agents": [ { "agent_name": "DD Director", "description": "Coordinates specialists and writes the final memo.", "system_prompt": ( "You are a senior due diligence director at a tier-1 investment firm. " "Synthesize specialist analyses into a board-ready memo with a clear " "recommendation (Invest / Pass / Watchlist)." ), "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Financial Analyst", "description": "Analyzes revenue, margins, balance sheet, and cash flow.", "system_prompt": ( "You are a sell-side financial analyst. Evaluate revenue growth, " "gross and operating margins, cash position, and debt load. Cite the " "specific metrics you would underwrite the investment against." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Market Analyst", "description": "Sizes the market and assesses competitive position.", "system_prompt": ( "You are a market research analyst. Estimate TAM/SAM, name the top " "three competitors, and call out the structural moat (or lack of one)." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, { "agent_name": "Risk Analyst", "description": "Identifies regulatory, operational, and execution risks.", "system_prompt": ( "You are a risk officer. List the top 5 risks (regulatory, operational, " "execution, macro, key-person). For each, give a likelihood and a " "mitigation." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, ], } ``` ## Step 3: Build the 50-Company Batch In a real workload, the watchlist comes from a portfolio database. Here we hard-code 50 tickers. ```python theme={null} WATCHLIST = [ ("NVIDIA", "NVDA"), ("Microsoft", "MSFT"), ("Apple", "AAPL"), ("Alphabet", "GOOGL"), ("Meta Platforms", "META"), ("Amazon", "AMZN"), ("Tesla", "TSLA"), ("Broadcom", "AVGO"), ("AMD", "AMD"), ("Salesforce", "CRM"), # ... fill out to 50 entries from your portfolio system ] batch_payload = [due_diligence_swarm(name, ticker) for name, ticker in WATCHLIST] print(f"Prepared batch of {len(batch_payload)} due-diligence swarms.") ``` ## Step 4: Submit the Overnight Job One POST. The server parallelizes the swarms behind the gateway. ```python theme={null} def run_overnight_batch(payload: list[dict]) -> list[dict]: response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload, timeout=3600, # one hour; large overnight runs may need more ) response.raise_for_status() return response.json() results = run_overnight_batch(batch_payload) ``` The endpoint returns one entry per swarm in the same order as the request, each with its own `status`, `swarm_name`, `usage`, and `result` (there is no `job_id` on batch entries — that only appears on the single-swarm `/v1/swarm/completions` response). Persist the array to disk before you start parsing — partial network failures are easier to recover from when you have the raw response saved. ## Step 5: Persist Per-Memo Files Drop one Markdown file per company into a dated folder so your team finds the memos waiting in the morning. ```python theme={null} def persist_results(results: list[dict], watchlist: list[tuple[str, str]]) -> Path: out_dir = Path("dd_runs") / datetime.utcnow().strftime("%Y-%m-%d") out_dir.mkdir(parents=True, exist_ok=True) total_cost = 0.0 for (name, ticker), swarm_result in zip(watchlist, results): status = swarm_result.get("status", "unknown") usage = swarm_result.get("usage", {}) or {} cost = usage.get("billing_info", {}).get("total_cost", 0.0) total_cost += float(cost or 0.0) memo_path = out_dir / f"{ticker}_{name.replace(' ', '_')}.md" output = swarm_result.get("result") or {} memo_path.write_text( f"# {name} ({ticker})\n\n" f"Status: {status}\n\n" f"Cost: ${cost}\n\n" f"---\n\n" f"{json.dumps(output, indent=2)}\n" ) (out_dir / "_summary.json").write_text( json.dumps({"total_cost": total_cost, "count": len(results)}, indent=2) ) return out_dir folder = persist_results(results, WATCHLIST) print(f"Memos written to: {folder}") ``` ## Step 6: Schedule the Overnight Run The simplest production deploy is a cron job on a small VM or a scheduled GitHub Action. Save the script above as `nightly_dd.py` and add to crontab: ```bash theme={null} # Run at 8pm every weekday 0 20 * * 1-5 /usr/bin/python3 /opt/dd/nightly_dd.py >> /var/log/dd.log 2>&1 ``` For zero-infrastructure scheduling, use a serverless cron platform (GitHub Actions `schedule:` cron, AWS EventBridge, Vercel Cron). The job itself is a single Python script — anywhere that can run Python on a schedule will work. ## Recovering From Partial Failures Each entry in the response carries its own `status`. Retry only the failed ones — never resubmit the full batch. ```python theme={null} def retryable(swarm_result: dict) -> bool: return swarm_result.get("status") != "success" failed = [ swarm for swarm, result in zip(batch_payload, results) if retryable(result) ] if failed: print(f"Retrying {len(failed)} failed swarms...") retry_results = run_overnight_batch(failed) # merge retry_results back into results by swarm_name / index ``` ## The Cost Math Pricing varies by model and current token rates — these numbers are illustrative. | Approach | Wall time | Direct cost | Burdened cost | | --------------------------------------- | ------------------------------- | -------------------- | -------------------------------- | | Junior analyst team writing 50 DD memos | \~250 hours (5 hrs per memo) | \$25,000 at \$100/hr | \$40,000+ with overhead | | One swarm at a time, sequentially | \~5-8 hours | \~\$75 | A workday of analyst babysitting | | **Batch swarm overnight, one POST** | **\~30-60 minutes server-side** | **\~\$75** | **\$75 + you were asleep** | **This overnight batch costs roughly \$50-\$100 to run for 50 four-agent due-diligence swarms. A junior analyst team would take \~250 hours at \$100/hour to produce the same fifty memos — about \$25,000 in direct labor.** Run it nightly across your watchlist and you have a permanent overnight research desk for the cost of a single analyst's coffee budget. ## Adapting the Pattern The same overnight-batch shape applies to any "N independent multi-agent jobs" workload: | Workload | One swarm per... | Agents inside each swarm | | ---------------------------- | ---------------------- | ------------------------------------------------ | | **M\&A pipeline review** | target company | DD director + financial + legal + technical | | **RFP response factory** | open RFP | proposal lead + writer + pricing + compliance | | **Clinical literature scan** | indication or molecule | senior MD + biostatistician + safety reviewer | | **Marketing market scan** | geography or persona | brand lead + copywriter + designer + performance | | **Vendor security review** | vendor | CISO + AppSec engineer + privacy counsel | Only the swarm template and the input list change. The batch envelope, scheduling, persistence, and retry pattern stay identical. ## Next Steps * [Batch Agent Completions at Scale](/docs/examples/examples/batch-agent-scale-tutorial) when a single agent per record is enough * [Batch Swarm Completions (Multi-Agent)](/docs/examples/examples/batch-swarm-completions) for the request-shape reference * [Supply Chain Hierarchical Swarm](/docs/examples/examples/supply-chain-swarm) for the inner hierarchical-swarm pattern this tutorial replicates 50 times # Catering Discovery Agent Source: https://docs.swarms.ai/docs/examples/examples/catering-agent A single-agent build for event catering discovery — strict JSON output, web search enabled, and structured vendor recommendations ready to feed into an outreach pipeline. ## What This Example Shows * A focused single-agent build for a real applied domain — event catering discovery * A strict, behaviorally-scoped `system_prompt` that pins the agent to structured JSON output * The top-level `tools_enabled` list (`"auto_search"`) for live vendor lookups with citations * How to parse the structured response and surface it to an end user * A cost callout: a single API call vs. hiring a catering consultant for an event This is the same pattern as the [Single Agent Overview](/docs/examples/examples/agent-overview), specialized for an applied vertical. The domain expertise lives entirely in the `system_prompt` — everything else is the standard agent payload. ## Why This Matters Event planners spend two to four hours on the first cut of catering research — pulling up review sites, comparing menus, checking dietary accommodations, hunting for current contact info, then formatting it all into a shortlist their stakeholders can scan. The job is mechanical and structured: find vendors that match a brief, surface the same fields for each one, flag what's unverified, and produce a ready-to-send outreach message. That's a single-agent job with web search and a strict output contract. The agent below is "Caterly" — it takes a catering brief, runs verified web lookups, and returns a structured vendor list plus a draft outreach message in one call. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` ```python theme={null} import json import os from typing import Any, Dict, Optional import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } ``` ## Step 2: Write the Strict System Prompt The system prompt is the contract. It tells the agent (1) what role it plays, (2) what behavioral rules to follow, (3) what fields each vendor must include, and (4) what to do when information is unverifiable. Every line below earns its place — drop one and the output drifts. ```python theme={null} SYSTEM_PROMPT = """ You are Caterly — a professional event catering discovery assistant. Your task is to find, evaluate, and recommend caterers that best match a user's event requirements. Always prioritize accuracy, transparency, and user-safety. Behavior rules: 1. Ask only necessary clarifying questions (if absolutely needed) — otherwise assume missing common defaults (guest_count=50, budget_per_person=$30, date=flexible). 2. When web search is enabled, perform web lookups and verify vendor contact and availability information; include citation for each vendor where possible. 3. For each recommended caterer, provide: name, short description, service types, price per person or range, contact info, menu highlights, dietary accommodations, travel/fee considerations, and a confidence rating with explanation. 4. Quote prices clearly and compute total estimated event cost = guest_count * price_per_person + service/travel fees. 5. Provide a "next steps" checklist and a ready-to-send caterer outreach message. 6. If asked to make bookings, provide only a booking proposal — never execute payments or contact vendors unless a tool is explicitly connected. 7. Never invent contact data — mark unverifiable items explicitly as "unverified". 8. If a vendor is unavailable, offer alternatives or timeline adjustments. 9. Output structured JSON followed by a short human summary. """ ``` Rule 7 is the load-bearing one. Without an explicit "never invent contact data" instruction, the model will happily hallucinate a plausible-sounding phone number for any restaurant it has weak data on. The `"unverified"` marker gives downstream code a stable signal to drop or re-verify before any outreach goes out. ## Step 3: Build the Agent Payload The top-level `tools_enabled` list is what turns Caterly from a vibes-only recommender into a web-grounded one. Passing `"auto_search"` in that list authorizes the platform to attach a live web-search tool (backed by Exa) to the agent for this request; `"web_scraper"` is also available if you need full-page scrapes instead of search snippets. ```python theme={null} def create_agent_payload(task: str, search_enabled: bool = True) -> Dict[str, Any]: return { "agent_config": { "agent_name": "Caterly - Event Catering Discovery Assistant", "description": ( "Professional event catering discovery assistant that finds, " "evaluates, and recommends caterers matching your event " "requirements. Provides detailed vendor information including " "pricing, dietary accommodations, contact details, menu " "highlights, and ready-to-send outreach messages. Performs web " "searches to verify vendor availability and contact information " "when enabled." ), "system_prompt": SYSTEM_PROMPT, "model_name": "gpt-4.1", "max_tokens": 3000, "temperature": 0.5, "role": "worker", "max_loops": 1, "tool_call_summary": True, "dynamic_temperature_enabled": True, }, "task": task, "tools_enabled": ["auto_search"] if search_enabled else [], } ``` ## Step 4: Call the Endpoint ```python theme={null} def run_caterly(task: str, search_enabled: bool = True) -> Dict[str, Any]: payload = create_agent_payload(task, search_enabled=search_enabled) response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() ``` ## Step 5: Extract the Structured Response The agent returns a JSON block followed by a short human-readable summary (per Rule 9). Pull the JSON for downstream automation; keep the summary for the end-user UI. ```python theme={null} def extract_content_from_outputs(outputs: Any) -> str: """Extract text content from the various output shapes the API returns.""" if outputs is None: return "" if isinstance(outputs, str): return outputs if isinstance(outputs, list): parts = [] for item in outputs: if isinstance(item, dict): content = item.get("content") or item.get("text") or item.get("message") if content: parts.append(str(content)) elif isinstance(item, str): parts.append(item) return "\n\n".join(parts) if parts else str(outputs) if isinstance(outputs, dict): return str( outputs.get("content") or outputs.get("text") or outputs.get("message") or json.dumps(outputs, indent=2) ) return str(outputs) def split_json_and_summary(content: str) -> Dict[str, Optional[str]]: """Caterly emits JSON first, then a human summary. Split them.""" import re match = re.search(r"\{[\s\S]*\}", content) raw_json = match.group(0) if match else None parsed: Optional[Any] = None summary = content if raw_json: try: parsed = json.loads(raw_json) summary = content.replace(raw_json, "").strip() except json.JSONDecodeError: parsed = None return {"json": parsed, "summary": summary} ``` ## Step 6: Run It End to End ```python theme={null} if __name__ == "__main__": task = ( "Find 5 caterers for a 70 person event in Mission, San Francisco. " "Prioritize a pizza caterer that can deliver to the event location. " "For each vendor, provide name, address, phone number, email, " "website, and a brief description of their services. Compute the " "total estimated event cost for each option." ) result = run_caterly(task, search_enabled=True) content = extract_content_from_outputs(result.get("outputs", "")) parsed = split_json_and_summary(content) print("\n=== STRUCTURED VENDORS ===") if parsed["json"]: print(json.dumps(parsed["json"], indent=2)) else: print("(no JSON block found — model drifted from the contract)") print("\n=== HUMAN SUMMARY ===") print(parsed["summary"]) usage = result.get("usage", {}) print(f"\nTokens: {usage.get('total_tokens', 0)} " f"Cost: ${usage.get('total_cost', 0):.4f}") ``` ## Production Notes The model is good at the contract but not perfect. Wrap your downstream automation in a JSON-schema validation step — reject the response and re-run with stricter instructions if a required field is missing. Never feed unvalidated agent output directly into a transactional outreach pipeline. Rule 7 in the system prompt is the safety net. When you parse the response, drop or re-verify any field marked `"unverified"` before it lands in a CRM or outreach tool. A hallucinated phone number that gets dialed is worse than no phone number at all. `temperature: 0.5` is tuned for menu creativity and outreach copy. If you want the same brief to return the same vendor list across runs, drop to `0.2` and accept slightly drier prose in exchange. For weddings, corporate conferences, or anything where a wrong vendor recommendation has real downside, run Caterly as the first node in a two-agent [Sequential Workflow](/docs/examples/examples/sequential-workflow) — Caterly proposes, a stricter verifier agent re-checks vendor availability against the same data sources. ## Cost vs. Hiring a Consultant A back-of-envelope comparison for a single 70-person event: | Approach | Time | Cost | | -------------------------------------------- | ---------------------------- | -------------------------------------------------- | | Hiring an event catering consultant | 2-4 hours of consultant time | \$300-\$800 retainer plus 10-15% vendor commission | | In-house planner doing the research manually | 2-4 hours of planner time | \~\$80-\$160 in loaded labor cost | | **Caterly via the Swarms API** | **\~30-60 seconds** | **\~\$0.05-\$0.20 per query** | For a venue or events agency running ten briefs a week, that's a four-figure monthly saving on the lookup step alone — and Caterly's structured JSON is ready to feed into your outreach automation without manual cleanup. Per-query cost varies with task complexity and `max_tokens`. The numbers above assume a typical 5-vendor brief with web search enabled. ## Build Your Own Domain Agent Swap the `SYSTEM_PROMPT` and `task` to retarget Caterly's shape to any "find, evaluate, recommend" domain: | Domain | system\_prompt focus | Suggested temperature | | -------------------------------------- | ------------------------------------------------------------------ | --------------------- | | **Wedding photographers** | Style match, package tiers, availability windows, sample portfolio | 0.5 | | **Corporate AV rental** | Equipment specs, setup/teardown logistics, insurance | 0.3 | | **Event venues** | Capacity, accessibility, parking, ADA, AV included | 0.4 | | **B2B vendor sourcing** | RFP fit, MSA terms, SOC2 status, references | 0.2 | | **Personal services (mover, cleaner)** | Service area, licensed/insured, hourly rate, availability | 0.4 | Everything else — payload shape, response handling, billing — stays identical. ## Next Steps * [Crypto Quant Agent](/docs/examples/examples/crypto-quant-agent) — same single-agent pattern specialized for cryptocurrency market analysis * [Single Agent Overview](/docs/examples/examples/agent-overview) — the full `agent_config` surface and every supported field * [MCP Integration](/docs/examples/examples/mcp-integration) — wire Caterly to a custom vendor-database MCP server instead of generic web search # Claude Fable 5 Source: https://docs.swarms.ai/docs/examples/examples/claude-fable-5 Run single agents, sequential pipelines, concurrent fan-outs, hierarchical swarms, and group chats on Anthropic's most capable model via the Swarms API. ## Overview This tutorial shows how to run Claude Fable 5 — Anthropic's most capable model, positioned above the Opus family — on the Swarms API. Fable 5 is built for the hardest reasoning and long-horizon agentic work: multi-step analysis, deep synthesis, and debates where agents must genuinely engage with each other's arguments. Using it requires exactly two things in your agent config: set `model_name` to `anthropic/claude-fable-5`, and leave `temperature` as `None` (the model rejects numeric sampling parameters). Everything else about your existing agents and swarms stays the same. The examples below walk through the full range of agent types — a standalone single agent, a sequential pipeline, a concurrent specialist fan-out, a director-led hierarchical swarm, a multi-agent group chat, and a cost-efficient mixed-model pattern that reserves Fable 5 for the synthesis step. ## What This Example Shows * The correct model name to use (`anthropic/claude-fable-5`) * Why `temperature` must be `None` for this model — never a number * A single agent on Claude Fable 5 * A `SequentialWorkflow` research pipeline * A `ConcurrentWorkflow` fan-out across specialist agents * A `HierarchicalSwarm` with an auto-generated director * A `GroupChat` debate between opposing analysts * A mixed-model pattern: Fable 5 as the aggregator, cheaper models as workers Claude Fable 5 is Anthropic's most capable generally available model, sitting above the Opus family. It is built for the hardest reasoning and long-horizon agentic work, and it is wired into every multi-agent primitive on the Swarms platform. Switching an existing agent to Fable 5 is a one-line change in your agent config. Claude Fable 5 does **not** accept the `temperature` parameter (or `top_p`). The field must be `None` — either leave it out of your `agent_config` entirely or set it explicitly to `None`, and the Swarms API will omit it from the upstream call. Passing any numeric value is rejected by Anthropic with a 400 error. ## Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Install the Swarms Python Client ```bash theme={null} pip install swarms-client python-dotenv ``` ## Step 3: Create the Client Every example below reuses this client: ```python theme={null} import json import os from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) ``` Fable 5 reasons deeply before answering, so individual calls can take noticeably longer than smaller models — especially on hard tasks. Keep the client `timeout` generous. ## Single Agent on Claude Fable 5 The minimal case. Note that `temperature` is explicitly `None` — this is the only sampling configuration Fable 5 accepts. ```python theme={null} result = client.agent.run( agent_config={ "agent_name": "Quant Research Analyst", "description": "A quantitative analyst specializing in derivatives pricing and risk.", "system_prompt": ( "You are a senior quantitative research analyst. You reason carefully " "through multi-step financial problems, state your assumptions explicitly, " "and show the intermediate calculations that support your conclusion." ), "model_name": "anthropic/claude-fable-5", "temperature": None, # required: Fable 5 rejects numeric temperature "max_loops": 1, "max_tokens": 8192, }, task=( "A 6-month European call on a non-dividend stock trades at $7.20. " "Spot is $100, strike is $105, and the risk-free rate is 4%. " "Back out the implied volatility and sanity-check it against a 25% " "historical vol. Is the option rich or cheap?" ), ) print(json.dumps(result, indent=4)) ``` **What changed from a typical agent call:** | Field | Before | With Fable 5 | | --------------- | -------------------------------------------- | ----------------------------------- | | `model_name` | `gpt-4.1`, `anthropic/claude-opus-4-8`, etc. | `anthropic/claude-fable-5` | | `temperature` | `0.5` (or any float) | `None` — or omit the field entirely | | Everything else | — | unchanged | ## SequentialWorkflow: Research → Analysis → Report Agents run one after another; each receives the previous agent's output. Fable 5's long-horizon reasoning makes it a strong fit for every stage of a pipeline like this. ```python theme={null} result = client.swarms.run( name="Fable 5 Research Pipeline", description="Researcher gathers facts, analyst interprets them, writer produces the deliverable.", swarm_type="SequentialWorkflow", task="Produce a briefing on the current state of solid-state battery commercialization.", max_loops=1, agents=[ { "agent_name": "Researcher", "description": "Gathers and organizes the relevant facts.", "system_prompt": ( "You are a research specialist. Collect the key facts, players, and " "timelines relevant to the task. Output a structured fact sheet." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Analyst", "description": "Interprets the research and extracts implications.", "system_prompt": ( "You are an industry analyst. Take the fact sheet you are given and " "identify the three most important implications, with reasoning." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Report Writer", "description": "Turns the analysis into a polished briefing.", "system_prompt": ( "You are a professional writer. Turn the analysis you receive into a " "concise executive briefing with a clear bottom line up front." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, ], ) print(json.dumps(result, indent=4)) ``` ## ConcurrentWorkflow: Specialist Fan-Out All agents receive the same task in parallel and answer independently — ideal when you want several expert perspectives at once. ```python theme={null} result = client.swarms.run( name="Fable 5 Deal Review Panel", description="Three specialists review the same acquisition target concurrently.", swarm_type="ConcurrentWorkflow", task=( "Evaluate the acquisition of a 200-person B2B SaaS company with $30M ARR, " "110% net revenue retention, and 18 months of runway. Flag the biggest risk " "from your specialty's point of view." ), max_loops=1, agents=[ { "agent_name": "Financial Diligence", "description": "Reviews the financial profile of the target.", "system_prompt": "You are an M&A financial diligence expert. Assess unit economics, burn, and valuation risk.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Technical Diligence", "description": "Reviews the technology and engineering organization.", "system_prompt": "You are a technical diligence expert. Assess architecture risk, technical debt, and key-person risk.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Legal Diligence", "description": "Reviews contracts, IP, and compliance exposure.", "system_prompt": "You are a legal diligence expert. Assess contract concentration, IP ownership, and regulatory exposure.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, ], ) print(json.dumps(result, indent=4)) ``` ## HierarchicalSwarm: Director + Workers You define only the workers — the framework auto-generates a director that decomposes the task, routes subtasks to each worker, and synthesizes the final answer. ```python theme={null} result = client.swarms.run( name="Fable 5 Markets Swarm", description="Director coordinates an ETF analyst and a stocks analyst.", swarm_type="HierarchicalSwarm", task=( "Compare the outlook for the SPY ETF and NVDA stock for the next quarter. " "Highlight the strongest signal for each." ), max_loops=1, agents=[ { "agent_name": "ETF Analyst", "description": "Analyzes broad-market and sector ETFs.", "system_prompt": ( "You are an ETF analyst. Given a ticker, summarize the fund's " "exposure, recent flows, and near-term outlook in under 200 words." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "role": "worker", "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Stocks Analyst", "description": "Analyzes individual equities.", "system_prompt": ( "You are an equity analyst. Given a ticker, summarize the company's " "fundamentals, catalysts, and near-term outlook in under 200 words." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "role": "worker", "max_loops": 1, "max_tokens": 4096, }, ], ) print(json.dumps(result, indent=4)) ``` ## GroupChat: Opposing Analysts Debate Agents discuss the task together and can respond to each other's arguments. Fable 5 is notably strong at pushing back on weak reasoning, which makes debates substantive rather than agreeable. ```python theme={null} result = client.swarms.run( name="Fable 5 Investment Debate", description="A bull and a bear debate the thesis; a moderator keeps score.", swarm_type="GroupChat", task="Debate: should a long-term portfolio overweight AI infrastructure stocks at current valuations?", max_loops=2, agents=[ { "agent_name": "Bull", "description": "Argues the optimistic case.", "system_prompt": "You argue the strongest honest bull case. Engage directly with the bear's specific points.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Bear", "description": "Argues the pessimistic case.", "system_prompt": "You argue the strongest honest bear case. Engage directly with the bull's specific points.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Moderator", "description": "Weighs both sides and summarizes.", "system_prompt": "You are a neutral moderator. After each round, identify which arguments landed and which were rebutted.", "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 4096, }, ], ) print(json.dumps(result, indent=4)) ``` ## Cost Pattern: Fable 5 Aggregator, Cheaper Workers Fable 5 reasons at length and spends more tokens than smaller models, so a common production pattern is `MixtureOfAgents` with lighter workers doing the breadth work and Fable 5 doing the final synthesis, where its reasoning matters most. ```python theme={null} result = client.swarms.run( name="Mixed-Model Mixture of Agents", description="Cheap workers draft perspectives; Fable 5 synthesizes the final answer.", swarm_type="MixtureOfAgents", task="What are the best practices for securing a multi-tenant Kubernetes cluster?", max_loops=1, agents=[ { "agent_name": "Network Security Worker", "description": "Covers network policy and segmentation.", "system_prompt": "You are a network security engineer. Cover network policies, segmentation, and ingress hardening.", "model_name": "claude-haiku-4-5-20251001", "max_loops": 1, "max_tokens": 2048, }, { "agent_name": "Identity Worker", "description": "Covers RBAC and workload identity.", "system_prompt": "You are an identity engineer. Cover RBAC, service accounts, and workload identity.", "model_name": "claude-haiku-4-5-20251001", "max_loops": 1, "max_tokens": 2048, }, { "agent_name": "Synthesizer", "description": "Merges worker outputs into one authoritative answer.", "system_prompt": ( "You are the lead security architect. Merge the specialist inputs into a " "single prioritized checklist, resolving any conflicts between them." ), "model_name": "anthropic/claude-fable-5", "temperature": None, "max_loops": 1, "max_tokens": 8192, }, ], ) print(json.dumps(result, indent=4)) ``` ## Using Fable 5 in Other Swarm Types Every other swarm architecture takes the same `model_name`. Drop `"model_name": "anthropic/claude-fable-5"` (with `temperature` left as `None`) into any agent inside any of these swarm configs: * `SequentialWorkflow` * `ConcurrentWorkflow` * `AgentRearrange` * `MixtureOfAgents` * `GroupChat` * `MajorityVoting` * `CouncilAsAJudge` * `MultiAgentRouter` * `HeavySwarm` * `LLMCouncil` * `DebateWithJudge` * `BatchedGridWorkflow` * `RoundRobin` * `PlannerWorkerSwarm` * `auto` ## Common Pitfalls You passed a numeric sampling parameter. Fable 5 removed `temperature`, `top_p`, and `top_k` entirely. Set `temperature` to `None` (or delete the field) in every agent config that uses `anthropic/claude-fable-5` — the Swarms API strips `None` fields before calling Anthropic. Expected. Fable 5 always reasons before answering and hard tasks can run for several minutes. Raise your client `timeout`, and prefer swarm architectures that parallelize independent work (`ConcurrentWorkflow`, `MixtureOfAgents`) over long sequential chains when latency matters. Fable 5 ships with additional safety classifiers and may decline certain requests (notably deep cybersecurity and research-biology content) that other models answer. If your workload lives near those domains, route it to `anthropic/claude-opus-4-8` instead. The Swarms API bills token usage at the same flat rate for every model — $6.50 per million input tokens and $18.50 per million output tokens — so Fable 5 costs the same per token as any other model here. See the [pricing page](/docs/documentation/resources/pricing) for current rates. ## Next Steps * Browse the [Multi-Agent Architectures](/docs/documentation/multi-agent/overview) catalog for more swarm types * Read the [Single Agent Overview](/docs/examples/examples/agent-overview) for the full agent config surface * See the [Claude Opus 4.8 example](/docs/examples/examples/claude-opus-4-8) for the other Anthropic frontier tier with the same no-temperature rule * See [Streaming](/docs/examples/examples/streaming) to stream Fable 5 tokens to your client in real time # Claude Opus 4.8 Source: https://docs.swarms.ai/docs/examples/examples/claude-opus-4-8 Run single agents and multi-agent swarms on Anthropic's strongest model via the Swarms API. ## What This Example Shows * How to point a single agent at Claude Opus 4.8 * How to run a hierarchical multi-agent swarm on Opus 4.8 * The correct model name to use (`anthropic/claude-opus-4-8`) * Why you should omit `temperature` for this model Claude Opus 4.8 is Anthropic's most capable reasoning model. It is wired into every multi-agent primitive on the Swarms platform — sequential workflows, hierarchical swarms, agent rearrange, group chats, mixture-of-agents, and more. Switching is a one-line change in your agent config. Claude Opus 4.8 has deprecated the `temperature` parameter. Do not pass `temperature` in your `agent_config` for this model — the Swarms API will omit it automatically when the field is unset, and the provider's own default will apply. Setting `temperature` to a number will be rejected by Anthropic with a 400. ## Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Install the Swarms Python Client ```bash theme={null} pip install swarms-client python-dotenv ``` ## Single Agent on Claude Opus 4.8 A minimal single-agent call. Note the `model_name` is the only thing that changes from any of your existing agent configs — `temperature` is intentionally absent. ```python theme={null} import json import os from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) result = client.agent.run( agent_config={ "agent_name": "Bloodwork Diagnosis Expert", "description": "An expert doctor specializing in interpreting and diagnosing blood work results.", "system_prompt": ( "You are an expert medical doctor specializing in the interpretation and diagnosis of blood work. " "Your expertise includes analyzing laboratory results, identifying abnormal values, " "explaining their clinical significance, and recommending next diagnostic or treatment steps. " "Provide clear, evidence-based explanations and consider differential diagnoses based on blood test findings." ), "model_name": "anthropic/claude-opus-4-8", "max_loops": 1, "max_tokens": 8192, }, task="Hemoglobin 10.2 g/dL, MCV 72 fL, ferritin 8 ng/mL — what's your diagnosis and next step?", ) print(json.dumps(result, indent=4)) ``` **What changed from a typical agent call:** | Field | Before | With Opus 4.8 | | --------------- | -------------------------------------------- | --------------------------- | | `model_name` | `gpt-4.1`, `claude-haiku-4-5-20251001`, etc. | `anthropic/claude-opus-4-8` | | `temperature` | `0.5` (or any float) | omit the field entirely | | Everything else | — | unchanged | ## Multi-Agent Swarm on Claude Opus 4.8 The same model name plugs into every multi-agent architecture. This example uses a `HierarchicalSwarm` where an auto-generated director coordinates two worker analysts — one for ETFs, one for individual stocks. ```python theme={null} import json import os from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) result = client.swarms.run( name="Markets Hierarchical Swarm", description="Director coordinates an ETF analyst and a stocks analyst.", swarm_type="HierarchicalSwarm", task=( "Compare the outlook for the SPY ETF and NVDA stock for the next quarter. " "Highlight the strongest signal for each." ), max_loops=1, agents=[ { "agent_name": "ETF Analyst", "description": "Analyzes broad-market and sector ETFs.", "system_prompt": ( "You are an ETF analyst. Given a ticker, summarize the fund's " "exposure, recent flows, and near-term outlook in under 200 words." ), "model_name": "anthropic/claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 4096, }, { "agent_name": "Stocks Analyst", "description": "Analyzes individual equities.", "system_prompt": ( "You are an equity analyst. Given a ticker, summarize the company's " "fundamentals, catalysts, and near-term outlook in under 200 words." ), "model_name": "anthropic/claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 4096, }, ], ) print(json.dumps(result, indent=4)) ``` For `HierarchicalSwarm`, you only need to define the worker agents — the director is automatically created and orchestrated by the framework. The director routes the task to each worker, collects their outputs, and synthesizes a final response. ## Using Opus 4.8 in Other Swarm Types Every other swarm architecture takes the same `model_name`. Drop `"model_name": "anthropic/claude-opus-4-8"` into any agent inside any of these swarm configs: * `SequentialWorkflow` * `ConcurrentWorkflow` * `AgentRearrange` * `MixtureOfAgents` * `GroupChat` * `MajorityVoting` * `CouncilAsAJudge` * `MultiAgentRouter` * `HeavySwarm` * `LLMCouncil` * `DebateWithJudge` * `BatchedGridWorkflow` * `RoundRobin` * `PlannerWorkerSwarm` * `auto` ## Common Pitfalls You set `temperature` in your `agent_config`. Remove the field entirely — the Swarms API will then omit it from the upstream Anthropic call. If you have legacy code that always sends a float, set it to `None` and rely on the Swarms API to strip it. Use `HierarchicalSwarm` (correctly spelled). Earlier versions of the API accepted the misspelled `HiearchicalSwarm`; the current schema only accepts the correct spelling. The Swarms API bills token usage at the same flat rate for every model — $6.50 per million input tokens and $18.50 per million output tokens. See the [pricing page](/docs/documentation/resources/pricing) for current rates. ## Next Steps * Browse the [Multi-Agent Architectures](/docs/documentation/multi-agent/overview) catalog for more swarm types * Read the [Single Agent Overview](/docs/examples/examples/agent-overview) for the full agent config surface * See [Streaming](/docs/examples/examples/streaming) to stream Opus 4.8 tokens to your client in real time # Client Setup & Basic Usage Source: https://docs.swarms.ai/docs/examples/examples/client-setup Learn how to set up the Swarms API client and perform basic operations like checking health, models, and rate limits. ## What This Example Shows * Setting up the Swarms API client * Checking API health status * Listing available models * Monitoring rate limits * Accessing swarm logs and availability ## Installation ```bash theme={null} pip3 install -U swarms-client ``` ## Get Your Swarms API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate a new API key 4. Store it securely in your environment variables ## Code ```python theme={null} import os import json from dotenv import load_dotenv from swarms_client import SwarmsClient # Load environment variables load_dotenv() # Initialize the client client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Check available models print("Available Models:") print(json.dumps(client.models.list_available(), indent=4)) # Check API health print("\nAPI Health:") print(json.dumps(client.health.check(), indent=4)) # Get swarm logs print("\nSwarm Logs:") print(json.dumps(client.swarms.get_logs(), indent=4)) # Check rate limits print("\nRate Limits:") print(json.dumps(client.client.rate.get_limits(), indent=4)) # Check swarm availability print("\nSwarm Availability:") print(json.dumps(client.swarms.check_available(), indent=4)) ``` ## Expected Output The script will output JSON responses showing: * List of available AI models * API health status * Recent swarm execution logs * Current rate limit usage * Swarm service availability ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Next Steps After running this example, you'll be ready to: * Create single agents for specific tasks * Build multi-agent swarms for complex workflows * Implement batch processing for multiple requests * Monitor and manage your API usage # Clinical Case Conference Swarm Source: https://docs.swarms.ai/docs/examples/examples/clinical-case-conference A multi-specialty tumor-board-style swarm where an Attending Physician synthesizes Radiology, Pathology, Cardiology, and Hospitalist input into a single treatment plan. ## What This Example Shows * A `HierarchicalSwarm` configured as a virtual **tumor board / case conference** * An Attending Physician (director) coordinating four specialist workers: Radiologist, Pathologist, Cardiologist, and Hospitalist * How the director **synthesizes** independent specialist opinions into one differential diagnosis, workup plan, and treatment recommendation * Concrete cost-per-case versus a real-world in-person multi-specialty consult * The difference between this pattern and a generic hospital staff swarm (the worker roster here is *physicians-only*, focused on diagnostic synthesis rather than nursing workflow) This example runs on premium swarm infrastructure. You will need an active Swarms account with available credits to execute it. Manage credits and plans at [https://swarms.world/platform/account](https://swarms.world/platform/account). **Medical disclaimer**: This example is for development and research purposes only. Output from this swarm is **not** a substitute for clinical judgment and **must not** be used for direct clinical decision-making without review by a licensed physician. The Swarms API is not a medical device, is not HIPAA-attested by default, and provides no diagnostic warranty. ## Why This Matters A real multi-disciplinary case conference (oncology tumor board, complex-cardiology rounds, MDT meeting) requires four to six specialists in the same room for an hour — easily **\$1,500 to \$2,500 per case** in loaded physician time, before scheduling delays. The job to be done is not "answer a medical question." It is **structured synthesis across specialties** so the attending walks out with one defensible plan. The hierarchical swarm replicates exactly that shape: parallel specialist opinions, then a director who decides. You spend cents, you wait under a minute, and you get an artifact you can hand to a licensed reviewer. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` Create a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` Get your key at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ## Step 2: Configure the Case Conference ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 3: Define the Patient Case This is the kind of multi-system presentation a single-specialist agent would underperform on — exactly the case worth taking to a board. ```python theme={null} patient_case = """ Patient: 62-year-old female, never-smoker Chief Complaint: 8 weeks of progressive right-upper-quadrant discomfort, 20-lb unintentional weight loss, intermittent low-grade fevers. Imaging: - CT chest/abdomen/pelvis with contrast: 4.2 cm hypodense mass in segment VII of the liver with arterial-phase enhancement and washout. Three sub-cm pulmonary nodules in the right lower lobe. No lymphadenopathy. - MRI liver: lesion is T2-hyperintense with restricted diffusion, no clear capsule. Background liver is non-cirrhotic. Pathology (core-needle biopsy of liver lesion): - Poorly differentiated carcinoma. CK7+, CK20-, TTF-1 weak focal+, Hep-Par1 negative, CDX2 negative. Ki-67 ~ 45%. Labs: - AFP 6 ng/mL, CEA 3.1 ng/mL, CA 19-9 42 U/mL - LFTs: AST 64, ALT 71, ALP 220, total bilirubin 1.0 - CBC: Hgb 10.8, MCV 88, platelets 410 - Troponin negative; BNP 380 pg/mL - ECG: sinus tachycardia at 104, no ischemic changes Cardiac history: - Hypertension, HFpEF (EF 55%), prior NSTEMI 2 years ago, on aspirin + atorvastatin + metoprolol. Performance status: ECOG 1. """ ``` ## Step 4: Build the Swarm The director's prompt is intentionally framed around **review, decide, and produce a single structured artifact** — not "write everything you know." Specialists each own one lane. ```python theme={null} payload = { "name": "Clinical Case Conference Swarm", "description": ( "Virtual tumor board: attending physician synthesizes radiology, " "pathology, cardiology, and hospitalist input into a single plan." ), "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( "Conduct a virtual multi-specialty case conference on the patient " "below. Each specialist should give an opinion limited to their " "domain. The attending must produce a final structured note with: " "(1) ranked differential diagnosis with reasoning, (2) recommended " "next workup with rationale, (3) initial treatment plan including " "cardiac-safety considerations, and (4) open questions for the " "treating team.\n\n" f"CASE:\n{patient_case}" ), "agents": [ { "agent_name": "Attending Physician", "description": ( "Conference chair. Reviews specialist input, decides, " "and produces the single integrated plan." ), "system_prompt": ( "You are the Attending Physician chairing a multi-disciplinary " "case conference. You do NOT re-do the specialists' work. " "Your job is to: (1) reconcile disagreements between " "specialists, (2) commit to a ranked differential, " "(3) order the next workup, (4) propose initial therapy " "with explicit cardiac-safety considerations given the " "patient's HFpEF and prior NSTEMI, and (5) list open " "questions for the treating team. Be decisive. Output a " "structured plan, not an essay." ), "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Radiologist", "description": "Body imaging specialist.", "system_prompt": ( "You are a board-certified diagnostic radiologist with " "abdominal-imaging fellowship training. Given the CT and " "MRI descriptions, characterize the dominant liver lesion " "(LI-RADS where applicable), comment on the pulmonary " "nodules, and propose the single most informative next " "imaging study. Stay in your lane: do not propose " "treatment. Be concise." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Pathologist", "description": "Anatomic and molecular pathology specialist.", "system_prompt": ( "You are an anatomic pathologist with experience in " "hepatobiliary and metastatic-of-unknown-primary cases. " "Given the IHC panel, interpret the lineage of the " "carcinoma, list the most likely primary sites in ranked " "order, and propose additional stains or molecular tests " "(NGS panel, specific markers) that would narrow it " "further. Do not propose treatment." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Cardiologist", "description": "Cardio-oncology and HFpEF specialist.", "system_prompt": ( "You are a cardiologist with cardio-oncology experience. " "Given this patient's HFpEF, prior NSTEMI, and current " "BNP and tachycardia, assess cardiac risk for the likely " "upcoming systemic therapies (platinum doublets, " "anthracyclines, immune checkpoint inhibitors, targeted " "agents). Recommend baseline cardiac workup and any " "drug-class restrictions or monitoring requirements. Do " "not stage the cancer or pick the regimen." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Hospitalist", "description": "Internal medicine generalist and care coordinator.", "system_prompt": ( "You are a hospitalist. Your job is the whole-patient " "view: nutrition (20-lb weight loss), anemia workup " "(Hgb 10.8), elevated ALP, performance-status trajectory, " "supportive care, and care-coordination handoffs. Flag " "anything that should be addressed before oncologic " "therapy begins. Do not duplicate the specialists' work." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, ], } ``` ## Step 5: Run the Conference ```python theme={null} response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) result = response.json() for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` Workers do not see each other's drafts — they each respond to the original task. The Attending Physician sees every specialist output and writes the final synthesis. This is the right shape for a case conference: independent opinions first, then one decision-maker. ## The Cost Story A real multi-specialty case conference is one of the most expensive things a hospital does: | Resource | Real-world cost | This swarm | | --------------------------------- | ----------------------- | -------------------------- | | Radiologist read + second opinion | \$150 – \$500 per study | Included | | Pathology IHC interpretation | \$200 – \$600 per case | Included | | Cardio-oncology consult | \$400 – \$800 per visit | Included | | Hospitalist coordination time | \$150 – \$300 per case | Included | | Tumor board attending time (1 hr) | \$400 – \$700 | Included | | **Per-case total (human team)** | **\$1,300 – \$2,900** | **Typically under \$1.00** | The point is not that the swarm replaces these clinicians. The point is that you can pre-screen, triage, and draft the conference note for the **same cost as a cup of coffee**, then put the licensed reviewer in the role they actually add value in: deciding. ## Differentiation From Related Examples * The [Hospital Medical Team Swarm](/docs/examples/examples/hospital-team) models a *bedside care team* (doctor + nurses + assistant) focused on intake and nursing tasks. This swarm models a *case conference of physicians-only* focused on diagnostic synthesis on a complex case. * The [ICD-10 Medical Analysis Swarm](/docs/examples/examples/icd-analysis) is a concurrent workflow for coding-level analysis. This swarm is hierarchical and produces a treatment plan, not codes. ## Next Steps * Try [Claude Opus 4.8](/docs/examples/examples/claude-opus-4-8) as the model for the Attending Physician for stronger synthesis * Adapt the worker roster for the [Supply Chain Hierarchical Swarm](/docs/examples/examples/supply-chain-swarm) pattern in any other domain * Run a portfolio of cases overnight using [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) # Build a Code Review Swarm: Security, Style, Tests, Architecture Source: https://docs.swarms.ai/docs/examples/examples/code-review-swarm A HierarchicalSwarm of specialist reviewer agents — Security, Style, Test Coverage, Architecture — coordinated by a Lead Reviewer that posts a single, decisive PR comment to GitHub. ## What This Example Shows * A `HierarchicalSwarm` with a Lead Reviewer (director) coordinating four specialist workers: Security, Style/Lint, Test Coverage, and Architecture * Tightly scoped system prompts that force each reviewer into a single lens with an explicit output format * A Lead Reviewer prompt that compresses every specialist's findings into one structured Markdown PR comment with a hard verdict * How to wire the swarm into a real GitHub PR — fetch the diff via the GitHub REST API and post the review back as a comment * A realistic cost comparison against a senior engineer reviewing the same PR This tutorial uses `HierarchicalSwarm` on `/v1/swarm/completions` — included in every paid Swarms tier. For teams reviewing hundreds of PRs a day across multiple repos, upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account) for higher rate limits and parallel execution. ## Why This Matters A single human reviewer cannot hold security, style, test coverage, and architecture in their head on the same pass — they pick one lens, miss the others, and the PR sits for two days while the author context-switches onto something else. That latency is what actually kills shipping speed: not the reviewing, the waiting. The job here is not to replace your senior engineer's signoff — it is to make sure that by the time they open the PR, every obvious finding is already in the thread, every missing test is already called out, and the only thing left for the human is the judgement call. One reviewer cannot catch everything. Four specialists running in parallel can. ## Step 1: Setup Install the dependencies and grab your API key from [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). You will also need a GitHub personal access token with `repo` scope to post the review back. ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-swarms-api-key" export GITHUB_TOKEN="your-github-pat" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Reviewer Team The Lead Reviewer owns the final comment. Each specialist owns exactly one lens and is told to ignore everything outside it. The output format is rigid on purpose — the Lead has to merge four streams into one PR comment in a single pass. ```python theme={null} LEAD_REVIEWER_PROMPT = ( "You are the Lead Reviewer on a pull request. Four specialists report to you: " "Security Reviewer, Style/Lint Reviewer, Test Coverage Reviewer, and Architecture " "Reviewer. Your job is NOT to re-review the diff yourself. Your job is to compress " "their findings into a single PR comment that an engineer can act on in five " "minutes.\n\n" "Output this exact Markdown structure and nothing else:\n\n" "## Verdict\n" " — one sentence on why.\n\n" "## Critical Issues\n" "\n\n" "## Suggestions\n" "\n\n" "## Test Gaps\n" "\n\n" "## Architecture Notes\n" "\n\n" "Be decisive. If any specialist flagged a Critical finding, the verdict is REQUEST " "CHANGES. Do not soften their language. Do not repeat the same finding across sections." ) SECURITY_REVIEWER_PROMPT = ( "You are a Security Reviewer. Read the diff and flag ONLY security issues: " "injection (SQL, command, template), authentication and authorization gaps, " "secrets in code, unsafe deserialization, SSRF, XSS, insecure crypto, missing " "input validation, and dangerous defaults. Ignore style, performance, and tests. " "For each finding output: SEVERITY (CRITICAL/HIGH/MEDIUM/LOW), file:line, the " "specific vulnerability, and the one-line fix. If the diff is clean, say 'No " "security findings.' Do not invent issues." ) STYLE_REVIEWER_PROMPT = ( "You are a Style and Lint Reviewer. Read the diff and flag ONLY code style " "issues: naming, dead code, unused imports, overly long functions, deeply " "nested branches, magic numbers, inconsistent error handling, and violations " "of the language's idiomatic conventions (PEP 8 for Python, Effective Go, " "etc.). Ignore correctness, security, and architecture. For each finding " "output: file:line, the smell, and the rewrite. Skip nits that a formatter " "would auto-fix." ) TEST_REVIEWER_PROMPT = ( "You are a Test Coverage Reviewer. Read the diff and identify behaviors that " "are new or changed but lack a corresponding test. For each gap output: the " "function or behavior, why it needs a test (edge case, regression risk, public " "API), and a one-line description of the test that should exist. Also flag any " "tests in the diff that assert on implementation details rather than behavior. " "Ignore style and security." ) ARCH_REVIEWER_PROMPT = ( "You are an Architecture Reviewer. Read the diff and flag ONLY design concerns: " "layering violations, leaky abstractions, circular dependencies, modules taking " "on responsibilities that belong elsewhere, new coupling between previously " "independent components, and patterns that will be expensive to undo in six " "months. Ignore line-level style and security. For each finding output: the " "concern, the affected files, and the structural alternative." ) def build_review_swarm(diff_text: str, pr_title: str, pr_description: str) -> dict: task = ( f"PR TITLE: {pr_title}\n\n" f"PR DESCRIPTION:\n{pr_description}\n\n" f"UNIFIED DIFF:\n{diff_text}\n\n" "Each specialist reviews the diff through their lens. The Lead Reviewer " "then produces the final PR comment." ) return { "name": "Code-Review-Swarm", "description": "Lead Reviewer coordinating Security, Style, Test, and Architecture specialists.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": task, "agents": [ { "agent_name": "Lead Reviewer", "description": "Director — synthesizes specialist findings into one PR comment.", "system_prompt": LEAD_REVIEWER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, }, { "agent_name": "Security Reviewer", "description": "Injection, authn/authz, secrets, crypto, validation.", "system_prompt": SECURITY_REVIEWER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.2, }, { "agent_name": "Style Reviewer", "description": "Naming, dead code, idiom violations, readability.", "system_prompt": STYLE_REVIEWER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Test Coverage Reviewer", "description": "Missing tests, weak assertions, regression risk.", "system_prompt": TEST_REVIEWER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Architecture Reviewer", "description": "Layering, coupling, abstractions, long-horizon design risk.", "system_prompt": ARCH_REVIEWER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, ], } ``` The Lead Reviewer's output is the comment you post to GitHub. The four specialist outputs are the audit trail — every flagged issue is fully traceable back to the reviewer who raised it. ## Step 3: Review a Single Diff Start with a single diff pasted in directly. This is the loop you will wire to GitHub in the next step. ```python theme={null} SAMPLE_DIFF = """\ diff --git a/app/auth.py b/app/auth.py index 1a2b3c..4d5e6f 100644 --- a/app/auth.py +++ b/app/auth.py @@ -10,6 +10,15 @@ from app.db import get_conn def get_user(user_id): conn = get_conn() cur = conn.cursor() - cur.execute("SELECT id, email FROM users WHERE id = %s", (user_id,)) + cur.execute(f"SELECT id, email, role FROM users WHERE id = {user_id}") return cur.fetchone() + +def reset_password(user_id, new_password): + conn = get_conn() + cur = conn.cursor() + cur.execute( + f"UPDATE users SET password = '{new_password}' WHERE id = {user_id}" + ) + conn.commit() + return True """ def run_review(diff_text: str, pr_title: str, pr_description: str) -> dict: payload = build_review_swarm(diff_text, pr_title, pr_description) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() def extract_lead_comment(result: dict) -> str: for output in result.get("output", []): if "Lead Reviewer" in output.get("role", ""): content = output["content"] if isinstance(content, list): content = "\n".join(str(c) for c in content) return str(content) return "" result = run_review( diff_text=SAMPLE_DIFF, pr_title="Add password reset endpoint", pr_description="Adds reset_password() and fixes a small bug in get_user().", ) print(extract_lead_comment(result)) billing = result.get("usage", {}).get("billing_info", {}) print(f"\n---\nReview cost: ${billing.get('total_cost', 0):.4f}") print(f"Execution time: {result.get('execution_time', 'n/a')}s") ``` The Lead Reviewer should come back with `REQUEST CHANGES`, a CRITICAL finding for the SQL injection in both queries, and a Test Gap entry for `reset_password`. That is the comment you post. ## Step 4: Wire It Into a GitHub PR In production you do not paste diffs — you point the swarm at a PR number. GitHub exposes both the unified diff and the issue-comments endpoint on every PR. ```python theme={null} GITHUB_API = "https://api.github.com" gh_headers = { "Authorization": f"Bearer {GITHUB_TOKEN}", "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", } def fetch_pr_diff(owner: str, repo: str, number: int) -> tuple[str, str, str]: # 1. Fetch PR metadata (title + body) as JSON meta = requests.get( f"{GITHUB_API}/repos/{owner}/{repo}/pulls/{number}", headers=gh_headers, timeout=30, ) meta.raise_for_status() pr = meta.json() # 2. Fetch the unified diff with the diff media type diff_resp = requests.get( f"{GITHUB_API}/repos/{owner}/{repo}/pulls/{number}", headers={**gh_headers, "Accept": "application/vnd.github.v3.diff"}, timeout=30, ) diff_resp.raise_for_status() return pr.get("title", ""), pr.get("body") or "", diff_resp.text def post_pr_comment(owner: str, repo: str, number: int, body: str) -> dict: response = requests.post( f"{GITHUB_API}/repos/{owner}/{repo}/issues/{number}/comments", headers=gh_headers, json={"body": body}, timeout=30, ) response.raise_for_status() return response.json() def review_github_pr(owner: str, repo: str, number: int) -> str: title, description, diff_text = fetch_pr_diff(owner, repo, number) result = run_review(diff_text, title, description) comment_body = extract_lead_comment(result) # Prepend a small attribution footer so the team knows what they're reading full_body = ( f"{comment_body}\n\n" f"---\n" f"_Automated review by Swarms `HierarchicalSwarm` " f"(Security + Style + Test + Architecture). " f"Cost: ${result['usage']['billing_info']['total_cost']:.4f}._" ) post_pr_comment(owner, repo, number, full_body) return full_body # Drop this into your CI on the `pull_request` event: # review_github_pr("your-org", "your-repo", int(os.environ["PR_NUMBER"])) ``` Running this from a GitHub Actions workflow on the `pull_request` event gives every PR a structured review comment within \~30 seconds of being opened. The author fixes the obvious findings before a human ever looks at the PR — which is the entire point. ## Real Cost vs. a Senior Reviewer | Scenario | Cost per PR | Monthly at 200 PRs | Annualized | | ------------------------------------------------------------------- | ------------------------ | ------------------ | ---------- | | Code Review Swarm (5 agents, mixed GPT-4.1 + Sonnet 4.5) | \~\$0.08 | \~\$16 | \~\$190 | | Senior engineer review (30 min @ \$200/hr fully loaded) | \$100 | \$20,000 | \$240,000 | | Senior engineer review with 1-day PR latency cost (lost throughput) | \$100 + opportunity cost | \$20,000+ | \$240,000+ | The swarm is not a replacement for your senior engineer's signoff — it is the reviewer who is always available at 2 AM, never misses the SQL injection, and never lets a PR sit for two days without a first pass. ## Next Steps * See [Tools in Swarms](/docs/examples/examples/tools-in-swarms) to give the reviewers a real linter, AST parser, or test runner as a tool call * Read [MCP Integration](/docs/examples/examples/mcp-integration) to connect the swarm to your internal code-search or SAST server over MCP * Browse the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) for the director-and-workers pattern with a deeper dive on routing # Concurrent Workflow Example Source: https://docs.swarms.ai/docs/examples/examples/concurrent-workflow Build a competitive intelligence dashboard with ConcurrentWorkflow ## Competitive Intelligence Dashboard This example demonstrates how to analyze multiple competitors simultaneously using ConcurrentWorkflow - perfect for parallel, independent tasks. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define Parallel Competitor Analysis Create one analyst agent per competitor - all run simultaneously: ```python theme={null} def analyze_competitors(competitors: list[str], industry: str) -> dict: """Analyze multiple competitors in parallel.""" # Create one agent per competitor agents = [] for competitor in competitors: agents.append({ "agent_name": f"{competitor} Analyst", "description": f"Analyzes {competitor}'s market position", "system_prompt": f"""You are a competitive intelligence analyst for {competitor}. Analyze across these dimensions: 1. COMPANY OVERVIEW - Founded, size, funding, leadership 2. PRODUCTS - Core offerings, recent launches, unique features 3. MARKET POSITION - Target segments, market share, partnerships 4. PRICING - Model, price points, enterprise approach 5. STRENGTHS & WEAKNESSES - Top 3 of each Be specific with facts and numbers.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }) swarm_config = { "name": f"Competitive Intelligence: {industry}", "description": "Parallel competitor analysis", "swarm_type": "ConcurrentWorkflow", "task": f"Analyze market position in the {industry} industry for: {', '.join(competitors)}", "agents": agents, "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 3: Run Parallel Analysis ```python theme={null} # Define competitors to analyze competitors = ["OpenAI", "Anthropic", "Google DeepMind", "Cohere", "Mistral AI"] # Run parallel analysis result = analyze_competitors(competitors, "AI/LLM Providers") # Display results execution_time = result.get("execution_time", 0) num_competitors = len(result.get("output", [])) print(f"Analyzed {num_competitors} competitors in {execution_time:.1f}s") print(f"Sequential would take ~{execution_time * num_competitors:.1f}s ({num_competitors}x slower)") for output in result.get("output", []): competitor = output["role"].replace(" Analyst", "") content = output["content"] print(f"\n{'='*50}") print(f"{competitor.upper()}") print(f"{'='*50}") print(content[:600] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` Analyzed 5 competitors in 28.4s Sequential would take ~142.0s (5x slower) ================================================== OPENAI ================================================== COMPANY OVERVIEW - Founded: 2015, San Francisco - Employees: ~1,500+ - Valuation: $80B+ (2024) - Leadership: Sam Altman (CEO) PRODUCTS - Core: GPT-4, ChatGPT, DALL-E, Whisper - Recent: GPT-4 Turbo, Custom GPTs, GPT Store... ================================================== ANTHROPIC ================================================== COMPANY OVERVIEW - Founded: 2021, San Francisco - Employees: ~500... Total cost: $0.2156 ``` ConcurrentWorkflow runs all agents in parallel. Use it when tasks are independent and don't need each other's output. You pay the same tokens whether sequential or concurrent, but finish faster. # McKinsey-Style Consulting Deliverable Generator Source: https://docs.swarms.ai/docs/examples/examples/consulting-deliverable-generator A HierarchicalSwarm that takes a client brief and produces a slide-by-slide market-entry deck outline — industry analysis, customer research, competitor landscape, financial model, and a partner-ready recommendation. ## What This Example Shows * A `HierarchicalSwarm` modeling a small consulting team: Engagement Director plus four senior workers * Four specialist workers — Industry Analyst, Customer Researcher, Competitor Analyst, Financial Modeler — each owning one function of the engagement * A director prompt that forces the final output into a slide-by-slide deck outline with chart callouts and a Pyramid-Principle recommendation * How to run the same engagement across a portfolio of clients in one call via `/v1/swarm/batch/completions` **Premium tier features used.** `HierarchicalSwarm` is available on every plan, but production workloads benefit from the Pro, Ultra, and Premium tiers (`/v1/swarm/batch/completions`, longer runs, higher concurrency). Upgrade or manage your plan at [https://swarms.world/platform/account](https://swarms.world/platform/account). ## Why This Matters A first-cut market entry analysis at a top consultancy is six weeks of two associates, an EM, and partial partner time — call it \$200k–\$500k of fees before the client sees a single slide. The actual analytic work in that first cut is bounded: size the market, map the competitors, profile the customer, sketch the unit economics, write a recommendation. This swarm does the full first cut in minutes so the partner can spend Friday afternoon arguing about the recommendation, not formatting slides. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Engagement Team Four workers each own one chapter of the deck. The Engagement Director sees every worker's output and is told, very explicitly, to produce a slide-by-slide outline — not a memo. ```python theme={null} def build_engagement(client_brief: str) -> dict: return { "name": "Consulting-Deliverable-Generator", "description": ( "Hierarchical engagement: Engagement Director coordinates four " "specialists and produces a partner-ready slide deck outline." ), "swarm_type": "HierarchicalSwarm", "task": client_brief, "max_loops": 1, "agents": [ { "agent_name": "Engagement Director", "description": "Senior partner-level lead. Synthesizes all worker outputs into a slide-by-slide deck.", "system_prompt": ( "You are the Engagement Director on a market-entry study. You have " "four specialists reporting to you: an Industry Analyst, a Customer " "Researcher, a Competitor Analyst, and a Financial Modeler.\n\n" "Your job is NOT to write a memo. Your job is to produce a " "partner-ready slide-by-slide deck outline using the Pyramid " "Principle (answer first, then supporting structure). Use this " "exact format for every slide:\n\n" "SLIDE N: \n" " Headline (governing thought, one sentence):\n" " Body (3-5 bullets, MECE):\n" " Chart / exhibit callout: <what visual goes here>\n" " Source: <which specialist(s) supplied this>\n\n" "Required slides, in order:\n" " 1. Title slide\n" " 2. Executive summary (the answer)\n" " 3. Context & client question\n" " 4. Market sizing (TAM/SAM/SOM)\n" " 5. Customer landscape & unmet need\n" " 6. Competitor landscape (2x2 or matrix)\n" " 7. Unit economics & financial model summary\n" " 8. Strategic options considered\n" " 9. Recommendation\n" " 10. Risks & mitigations\n" " 11. 90-day implementation roadmap\n" " 12. Appendix index\n\n" "The Recommendation slide must give a clear ENTER / ENTER-PARTNERED / " "WAIT / PASS verdict with the two strongest supporting reasons and " "the single largest risk." ), "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Industry Analyst", "description": "Sizes the market and profiles industry structure.", "system_prompt": ( "You are a senior industry analyst. For the client's target market: " "estimate TAM, SAM, and SOM with named assumptions; describe value " "chain and economics; identify regulatory regime; flag the three " "structural trends most likely to move the market over the next " "five years. Cite the type of source you would pull each number " "from (e.g., 'FDIC Call Reports', 'SBA loan data') even if you " "estimate from prior knowledge. Be quantitative." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, }, { "agent_name": "Customer Researcher", "description": "Profiles target customers, segments, and unmet needs.", "system_prompt": ( "You are a senior customer research lead. Segment the target " "customer base into 3-4 archetypes with named attributes (size, " "vertical, sophistication, geography). For each segment: estimate " "size, willingness to pay, top three jobs-to-be-done, and the " "single largest unmet need today. Identify which segment is the " "best beachhead and why." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, }, { "agent_name": "Competitor Analyst", "description": "Maps the competitive landscape and identifies whitespace.", "system_prompt": ( "You are a senior competitor analyst. Identify the top 5-8 " "competitors the client will face, including incumbents and " "challengers. For each: business model, served segment, " "estimated share, key strength, key weakness. Position them on " "a 2x2 of your choosing (state the axes explicitly) and " "identify the whitespace the client could occupy. Call out any " "competitor whose response could realistically kill the entry." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Financial Modeler", "description": "Builds the unit-economics and three-year P&L sketch.", "system_prompt": ( "You are a senior financial modeler. Produce a defensible " "first-cut model: unit economics (revenue per customer, gross " "margin, CAC, payback period), three-year P&L sketch with stated " "assumptions, capital required to reach breakeven, and the two " "or three assumptions that most move the answer. Identify the " "single most important sensitivity and state which way it cuts." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, ], } ``` <Note> For `HierarchicalSwarm` you only define the workers and the coordinator — the framework handles the routing, output collection, and synthesis pass. The director sees every worker's output before producing the final deck. </Note> ## Step 3: Run the Engagement The client brief is the only input. Replace it with whatever your client actually asked for. ```python theme={null} client_brief = ( "We are a mid-market regional bank with $14B in assets, headquartered in " "the Southeast U.S. Our retail and CRE books are mature. Our board is " "asking us to evaluate whether to enter SMB lending (loans of $50k-$2M to " "businesses with under $25M revenue) as a third growth pillar. Build us a " "market-entry analysis: should we enter, how, and what would it take?" ) payload = build_engagement(client_brief) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) result = response.json() for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600] + "...\n") usage = result.get("usage", {}) billing = usage.get("billing_info", {}) print(f"\nTotal cost: ${billing.get('total_cost', 0):.4f}") print(f"Execution time: {result.get('execution_time', 'n/a')}s") ``` The Engagement Director's output is your deck outline — a slide-by-slide structure an associate can drop into PowerPoint or a partner can edit directly. The individual worker outputs become your appendix and your supporting workbooks. ## Step 4: Scale to a Portfolio of Clients Boutiques and corporate strategy teams routinely run the same study shape against a portfolio: every regional bank in a watchlist, every PE portfolio company evaluating an adjacent market, every market a multinational is screening for entry. Use `/v1/swarm/batch/completions` to run the same engagement template against each brief in one call. ```python theme={null} client_briefs = [ "Mid-market regional bank evaluating SMB lending entry — see prior brief.", "$3B AUM PE firm evaluating a roll-up in U.S. veterinary clinics.", "European industrial OEM evaluating direct-to-consumer entry in North America.", # ...add as many as you need ] batch_payload = [build_engagement(b) for b in client_briefs] batch_response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=batch_payload, timeout=1800, ) decks = batch_response.json() print(f"Decks produced: {len(decks)}") ``` <Note> The batch endpoint is Pro/Ultra/Premium-only. See [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) for the full reference. </Note> ## Cost vs. a Real Engagement <Info> **Real numbers.** A first-cut market-entry analysis at a top-tier consultancy typically runs **\$200k–\$500k**: two associates and an engagement manager for four to six weeks, plus partial partner time at roughly \$800/hour. A four-analyst week alone is on the order of \$250k in billables. The swarm above runs the same first-cut analysis end-to-end for **under \$5 per deck**, finishes in minutes instead of weeks, and produces a slide-by-slide outline a partner can edit directly. The partner is still the partner — the swarm just removes the four weeks of associate-level synthesis that used to sit between the question and the recommendation. </Info> ## Next Steps * [Supply Chain Hierarchical Swarm](/docs/examples/examples/supply-chain-swarm) — same `HierarchicalSwarm` pattern applied to operations work * [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) — the underlying pattern, with a software-team example * [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) — fan the engagement template across a portfolio of clients # Conversation History (Multi-Turn Agents) Source: https://docs.swarms.ai/docs/examples/examples/conversation-history Build chatbots and research assistants that remember earlier turns by threading the history field through /v1/agent/completions. ## What This Example Shows * How to pass prior turns to an agent using the `history` field on `/v1/agent/completions` * The exact `{role, content}` message shape the API expects * How to thread the assistant's reply back into the next request to keep context * A worked support-chatbot loop across three turns * The most common mistake — silently dropping context — and how to avoid it <Info> The Swarms API is stateless. Each call to `/v1/agent/completions` starts a fresh agent. To get multi-turn behavior, *you* carry the conversation: send every prior `user` and `assistant` message back on the `history` field of the next request. </Info> ## Why This Matters Most real products — support chatbots, multi-turn research assistants, onboarding flows, interactive analysts — only feel useful once the agent remembers earlier turns. Without that, your user has to re-state their problem on every message. The `history` parameter is the single foundational primitive that turns a one-shot completion into a real conversation, and threading it correctly is the difference between an agent that feels alive and one that feels amnesiac. ## Step 1: Setup ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} def build_agent_config(): return { "agent_name": "Customer Support Agent", "description": "A friendly e-commerce customer support agent that helps with orders, returns, and refunds.", "system_prompt": ( "You are a helpful customer support agent for an online retailer. " "Greet customers warmly, ask for the information you need to help " "(order number, email on file, etc.), remember details the customer " "has already shared earlier in the conversation, and walk them through " "next steps clearly and concisely." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 2048, } def call_agent(task: str, history: list | None = None) -> dict: """Send one turn to /v1/agent/completions, optionally threading history.""" payload = { "agent_config": build_agent_config(), "task": task, } if history: payload["history"] = history response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=120, ) response.raise_for_status() return response.json() def extract_reply(result: dict) -> str: """Pull the assistant's final text out of an AgentCompletion response. The /v1/agent/completions response shape is: {"job_id": ..., "outputs": [...], "usage": {...}, ...} where `outputs` is a list of {"role": ..., "content": ...} dicts. We want the last assistant message — i.e. the last entry whose role is not "user". """ outputs = result.get("outputs") if isinstance(outputs, list): for item in reversed(outputs): if not isinstance(item, dict): continue role = (item.get("role") or "").lower() if role in ("user", "system"): continue content = item.get("content") if isinstance(content, list): return " ".join(str(c) for c in content) if content: return str(content) # Fall back to whatever the API returned — print raw so you can inspect it. return json.dumps(outputs, indent=2) if outputs is not None else json.dumps(result, indent=2) ``` ## Step 2: Turn 1 — Greeting (No History) The first turn has no prior context, so `history` is omitted. The agent answers from a clean slate. ```python theme={null} turn_1_task = "Hi there!" turn_1_result = call_agent(task=turn_1_task) turn_1_reply = extract_reply(turn_1_result) print("USER: ", turn_1_task) print("ASSISTANT:", turn_1_reply) ``` The agent greets the customer back and likely asks how it can help — standard opening turn, nothing to remember yet. <Note> The Swarms API accepts `history` as a list of `{role, content}` dicts. Valid roles are `"user"` and `"assistant"`. The `system_prompt` lives in `agent_config` — do NOT prepend a `{"role": "system", ...}` message into `history`. </Note> ## Step 3: Turn 2 — "Where is my order?" Append the previous user message and assistant reply into `history`, then send the next user message as the new `task`. ```python theme={null} history = [ {"role": "user", "content": turn_1_task}, {"role": "assistant", "content": turn_1_reply}, ] turn_2_task = "Where is my order? It was supposed to arrive yesterday." turn_2_result = call_agent(task=turn_2_task, history=history) turn_2_reply = extract_reply(turn_2_result) print("USER: ", turn_2_task) print("ASSISTANT:", turn_2_reply) ``` Because turn 1 is in `history`, the agent treats this as a continuation of an ongoing chat rather than a brand-new session — it doesn't re-greet, and it can reference the earlier hello if relevant. ## Step 4: Turn 3 — "Actually, I want a refund" The customer pivots. Append turn 2 to `history`, then ask for a refund. With the full thread in context, the agent connects the refund request to the missing-order complaint from turn 2 instead of treating it as a fresh, unrelated request. ```python theme={null} history.extend([ {"role": "user", "content": turn_2_task}, {"role": "assistant", "content": turn_2_reply}, ]) turn_3_task = "Actually, forget the tracking — I just want a refund." turn_3_result = call_agent(task=turn_3_task, history=history) turn_3_reply = extract_reply(turn_3_result) print("USER: ", turn_3_task) print("ASSISTANT:", turn_3_reply) ``` By turn 3 the agent has the full conversational arc — greeting, missing-order complaint, pivot to refund — and can route the customer to the refund flow while citing the original order issue as the reason. Without `history`, it would ask "refund for what?" and the customer would have to start over. ## Step 5: Wrap It in a Reusable Chat Loop The full pattern collapses into a tiny REPL you can drop into a CLI, a webhook handler, or a websocket session. ```python theme={null} def chat_loop(): history: list[dict] = [] print("Support Assistant ready. Type 'quit' to exit.\n") while True: user_msg = input("You: ").strip() if user_msg.lower() in {"quit", "exit"}: break result = call_agent(task=user_msg, history=history or None) reply = extract_reply(result) print(f"Assistant: {reply}\n") history.append({"role": "user", "content": user_msg}) history.append({"role": "assistant", "content": reply}) if __name__ == "__main__": chat_loop() ``` <Warning> **Common mistake — losing context by overwriting instead of appending.** The most frequent bug we see is sending only the *latest* user/assistant pair as `history`, or rebuilding `history` from scratch each turn. The agent then loses everything before that pair. `history` is a transcript of the whole conversation so far; you append to it every turn, you do not replace it. If your bot suddenly "forgets" what the user said three messages ago, this is almost always the cause. </Warning> <AccordionGroup> <Accordion title="Should I include the latest user `task` inside `history`?"> No. Send the new turn as `task` and put only the *prior* turns in `history`. The API stitches them together internally. Putting the current question in both places will duplicate it in the model's view. </Accordion> <Accordion title="How long can `history` get before I should trim?"> It scales with the model's context window. For long sessions, periodically summarize older turns into a single `assistant` message and keep only the last N raw turns verbatim — same pattern as any other chat application. </Accordion> <Accordion title="Can I persist history across processes?"> Yes. `history` is just JSON. Store it in your database keyed by session/user ID and rehydrate it on the next request. The Swarms API holds no server-side session state for `/v1/agent/completions`. </Accordion> </AccordionGroup> ## Next Steps * [Single Agent Overview](/docs/examples/examples/agent-overview) — the full `agent_config` surface, including tools and vision * [Streaming Responses](/docs/examples/examples/streaming) — stream the assistant's reply token-by-token while still threading history * [Sub-Agent Delegation](/docs/examples/examples/sub-agent-delegation) — let a conversational agent hand off specialist sub-tasks mid-thread # Council as Judge Example Source: https://docs.swarms.ai/docs/examples/examples/council-as-judge Build a multi-dimensional AI response evaluation system with CouncilAsAJudge ## AI Response Quality Evaluation System This example demonstrates how to evaluate AI-generated content across multiple quality dimensions using CouncilAsAJudge — perfect for quality assurance, model benchmarking, and response improvement workflows. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define the Evaluation Council Create a panel of specialist evaluator agents — each focuses on a single quality dimension — plus an aggregator that synthesizes their findings into a comprehensive report: ```python theme={null} def evaluate_response(task: str, response_to_evaluate: str) -> dict: """Evaluate an AI response across multiple quality dimensions.""" swarm_config = { "name": "Response Quality Council", "description": "Multi-dimensional AI response evaluation", "swarm_type": "CouncilAsAJudge", "task": f"""Evaluate the following AI-generated response: ORIGINAL TASK: {task} RESPONSE TO EVALUATE: {response_to_evaluate}""", "agents": [ { "agent_name": "Accuracy Judge", "description": "Evaluates factual accuracy and correctness", "system_prompt": """You are an expert accuracy evaluator. Assess the response for: 1. Factual correctness — cross-reference claims against known facts 2. Technical accuracy — verify technical details and specifications 3. Internal consistency — check for contradictions within the response 4. Source credibility — evaluate whether claims are well-supported 5. Temporal accuracy — flag outdated or time-sensitive information Provide specific examples of accurate and inaccurate claims.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Helpfulness Judge", "description": "Evaluates practical value and completeness", "system_prompt": """You are an expert helpfulness evaluator. Assess the response for: 1. Direct alignment with the user's question and intent 2. Completeness — are all aspects of the question addressed? 3. Actionability — can the user act on this information? 4. Clarity of examples and explanations 5. Proactive coverage of edge cases and follow-up questions Identify what's useful and what's missing.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Harmlessness Judge", "description": "Evaluates safety and ethical considerations", "system_prompt": """You are an expert safety evaluator. Assess the response for: 1. Harmful stereotypes, biases, or discriminatory content 2. Potential misuse scenarios or dangerous applications 3. Promotion of unsafe practices 4. Appropriate safety disclaimers and caveats 5. Audience sensitivity and tone appropriateness Flag any safety concerns with severity levels.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Coherence Judge", "description": "Evaluates structure and logical flow", "system_prompt": """You are an expert coherence evaluator. Assess the response for: 1. Logical flow and argument structure 2. Information hierarchy and organization 3. Consistent terminology and clear definitions 4. Smooth transitions between ideas 5. Overall readability and comprehension Reference specific sections that are well-structured or problematic.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Conciseness Judge", "description": "Evaluates communication efficiency", "system_prompt": """You are an expert conciseness evaluator. Assess the response for: 1. Redundant information or repetition 2. Unnecessary qualifiers or verbose expressions 3. Information density — is every sentence adding value? 4. Directness of communication 5. Appropriate length for the question's complexity Identify specific areas that could be trimmed without losing value.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Instruction Adherence Judge", "description": "Evaluates compliance with original requirements", "system_prompt": """You are an expert instruction adherence evaluator. Assess the response for: 1. Coverage of all explicit requirements in the prompt 2. Adherence to specified constraints and formats 3. Scope appropriateness — no over- or under-delivery 4. Alignment with implicit expectations 5. Format and structure compliance Check each requirement individually and note compliance status.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 4: Run the Evaluation ```python theme={null} # Define the original task and the response to evaluate original_task = """ Explain the differences between REST and GraphQL APIs. Include pros and cons of each, and recommend when to use which approach. """ ai_response = """ REST and GraphQL are two popular approaches to building APIs. REST (Representational State Transfer) uses fixed endpoints where each URL represents a resource. GET /users returns all users, GET /users/1 returns a specific user. It's simple and cacheable but can lead to over-fetching (getting more data than needed) or under-fetching (requiring multiple requests). GraphQL uses a single endpoint where clients specify exactly what data they need via queries. This eliminates over-fetching and reduces round trips. However, it adds complexity with schema design, makes caching harder, and can suffer from N+1 query problems on the backend. Use REST for simple CRUD APIs, public APIs needing easy caching, and teams new to API design. Use GraphQL for complex data relationships, mobile apps needing bandwidth efficiency, and applications with diverse frontend needs. """ # Run evaluation result = evaluate_response(original_task, ai_response) # Display dimension evaluations for output in result.get("output", []): judge = output["role"] content = output["content"] print(f"\n{'='*60}") print(f"{judge.upper()}") print(f"{'='*60}") if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:800] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` ============================================================ ACCURACY_JUDGE ============================================================ Technical Analysis (ACCURACY Dimension): The response correctly defines REST as using fixed endpoints and provides appropriate examples (GET /users, GET /users/1). The identification of over-fetching and under-fetching as REST limitations is accurate. Strengths: - Core concepts for both REST and GraphQL are correct - N+1 query problem in GraphQL is accurately identified - Caching difficulty in GraphQL is a valid concern Areas for Improvement: - "REST uses fixed endpoints" is an oversimplification — REST is an architectural style, not strictly tied to fixed endpoints - Missing mention of HTTP methods (POST, PUT, DELETE) which are fundamental to REST... ============================================================ HELPFULNESS_JUDGE ============================================================ Technical Analysis (HELPFULNESS Dimension): The response aligns with the user's request by defining both REST and GraphQL and outlining their pros and cons. Strengths: - Clear side-by-side comparison structure - Actionable recommendation section at the end - Real-world use case suggestions for each approach Gaps: - Lacks depth in practical scenarios and real-world examples - No code examples showing the difference in practice - Missing discussion of tooling ecosystem - No mention of hybrid approaches or migration strategies... ============================================================ COHERENCE_JUDGE ============================================================ Technical Analysis (COHERENCE Dimension): The response begins with a clear introduction but lacks a structured layout that distinguishes pros and cons clearly. Strengths: - Consistent parallel structure when comparing approaches - Clear topic sentences for each paragraph Issues: - Pros and cons are mixed within definitions rather than clearly delineated - Transition from REST to GraphQL is abrupt — no bridging sentence - The recommendation section could be formatted as a comparison table for better scannability... ============================================================ AGGREGATOR_AGENT ============================================================ Comprehensive Technical Report Executive Summary: The response effectively compares REST and GraphQL APIs with technical neutrality and directness. It scores well on accuracy and coherence but has room for improvement in depth and formatting. Cross-Dimensional Patterns: - All judges noted the response is correct but surface-level - Helpfulness and instruction adherence both flagged missing code examples and deeper technical detail - Coherence and conciseness judges identified formatting improvements Prioritized Recommendations: 1. Add structured formatting for pros/cons (high impact) 2. Include practical code examples (high impact) 3. Expand technical depth on caching and performance (medium impact) 4. Include a comparison table for quick reference (medium impact) Total cost: $0.1606 ``` ### Step 5: Batch Evaluation for Model Comparison Use CouncilAsAJudge to compare responses from different models on the same task: ```python theme={null} def compare_model_responses(task: str, responses: dict[str, str]) -> dict: """Evaluate multiple model responses and compare quality.""" results = {} for model_name, response in responses.items(): print(f"Evaluating {model_name}...") results[model_name] = evaluate_response(task, response) # Compare final aggregator reports print(f"\n{'='*60}") print("MODEL COMPARISON SUMMARY") print(f"{'='*60}") for model_name, result in results.items(): outputs = result.get("output", []) # Get the aggregator's final report (last output) if outputs: final = outputs[-1]["content"] if isinstance(final, list): final = ' '.join(str(item) for item in final) print(f"\n--- {model_name} ---") print(str(final)[:400] + "...") return results # Compare two model responses task = "Explain database indexing and when to use composite indexes." responses = { "Response A": "Database indexing creates a data structure that improves query speed...", "Response B": "An index in a database is like a book's index — it helps you find data faster..." } comparison = compare_model_responses(task, responses) ``` <Note> CouncilAsAJudge evaluates responses across 6 dimensions in parallel: accuracy, helpfulness, harmlessness, coherence, conciseness, and instruction adherence. Each dimension judge works independently, then an aggregator synthesizes all evaluations into a single comprehensive report with prioritized recommendations. </Note> # Crypto On-Chain Whale Tracker: Multi-Chain Movement Classification Source: https://docs.swarms.ai/docs/examples/examples/crypto-onchain-whale-tracker A ConcurrentWorkflow that watches the top 100 wallets across ETH, BTC, SOL, and Base every block, classifies every movement, and alerts before the chart catches up. Every twelve seconds the largest wallets on four chains get classified — and an hour before the spot move shows up on a chart, your Slack already knows where the flow is going. ## What This Example Shows * A `ConcurrentWorkflow` that runs four per-chain monitors (ETH, BTC, SOL, Base) in parallel — one swarm call per block, every block * MCP wiring for Alchemy / Infura / Helius RPC endpoints so each chain agent reads its native mempool and block stream directly * Function tools that classify every whale tx: CEX inflow/outflow, OTC, DEX swap, or bridge — with wallet-label enrichment * Sustained polling rate-limit math: ETH block time of 12 seconds compounds to \~7,200 swarm calls/day, blowing through the Free tier's per-day cap after a few hours * Real-time alert routing into Slack and Discord with severity scoring, including programmatic muting on quiet hours <Info> Continuous block-by-block polling breaches the Free tier per-day cap within a few hours of running. Observability for missed alerts — execution traces, retry queues, and per-agent latency — is Premium-only. See the [Rate Limits documentation](/docs/documentation/resources/ratelimits) before you flip this loop on in production. </Info> ## Why This Matters Whale wallets historically lead the tape by 15 to 60 minutes — a \$40M wBTC pull off Coinbase Prime, a fresh deposit into a Binance OTC sub-account, a bridge from Base to Solana — these are the movements that show up on a price chart later as a green or red candle. The alpha is not in seeing the transaction (any block explorer does that). The alpha is in classifying it inside the same block: is this a market maker rebalancing, an OTC settlement that will hit spot in 20 minutes, or a known fund unwinding into a bridge? Sub-block latency on that classification — and the wallet label that makes it tradeable — is the entire edge. A `ConcurrentWorkflow` lets you process all four major L1/L2 chains in the same swarm call, so when the ETH monitor sees a whale deposit on block N, the Base monitor on that same swarm call has already seen the bridge ack on the other side. ## The Architecture ``` ┌──────────────────────┐ │ Block Trigger Loop │ │ (every 12 seconds) │ └──────────┬───────────┘ │ ▼ ┌──────────────────────────────────────────┐ │ ConcurrentWorkflow │ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ ETH │ │ BTC │ │ SOL │ │ Base │ │ │Monitor │ │Monitor │ │Monitor │ │Monitor │ │ └───┬────┘ └───┬────┘ └───┬────┘ └───┬────┘ └──────┼───────────┼───────────┼───────────┼─────┘ │ │ │ │ └───────────┴─────┬─────┴───────────┘ ▼ ┌──────────────────────────┐ │ Movement Classifier │ │ (grok-4) │ └──────────────┬───────────┘ ▼ ┌──────────────────────────┐ │ Alert Generator │ │ (claude-sonnet-4.5) │ └──────────────┬───────────┘ ▼ ┌──────────────────────────┐ │ Slack / Discord │ └──────────────────────────┘ ``` ## Step 1: Setup Install the dependencies and pull keys for Swarms, your RPC provider, an explorer for label lookups, and your alert webhook. ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-swarms-key" export ALCHEMY_API_KEY="your-alchemy-key" export ETHERSCAN_API_KEY="your-etherscan-key" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..." ``` ```python theme={null} import json import os import time import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` The four per-chain agents each point to a different MCP server via the `mcp_url` field on the agent config. The Alchemy SSE endpoint is the simplest path for ETH and Base; Helius covers Solana; an Esplora/mempool.space MCP covers BTC. You can run all four as separate containers or terminate them behind a single proxy — the swarm only cares about the URL. ```python theme={null} MCP_URLS = { "ETH": "https://your-alchemy-mcp.internal/eth/sse", "BTC": "https://your-mempool-mcp.internal/btc/sse", "SOL": "https://your-helius-mcp.internal/sol/sse", "BASE": "https://your-alchemy-mcp.internal/base/sse", } ``` ## Step 2: Define the Function Tools Function tools are OpenAI-schema JSON. Define them once, attach them per-agent. The classifier and chain agents share the lookup tools; the alert generator only gets `post_whale_alert`. ```python theme={null} FETCH_RECENT_BLOCK = { "type": "function", "function": { "name": "fetch_recent_block", "description": "Return the full block (header + transactions) for a given chain at a given block number.", "parameters": { "type": "object", "properties": { "chain": { "type": "string", "enum": ["ETH", "BTC", "SOL", "BASE"], }, "block_number": {"type": "integer"}, }, "required": ["chain", "block_number"], }, }, } GET_WALLET_TRANSACTIONS = { "type": "function", "function": { "name": "get_wallet_transactions", "description": "Return all transactions involving a specific wallet address since a given block.", "parameters": { "type": "object", "properties": { "address": {"type": "string"}, "since_block": {"type": "integer"}, }, "required": ["address", "since_block"], }, }, } LOOKUP_WALLET_LABEL = { "type": "function", "function": { "name": "lookup_wallet_label", "description": "Resolve a wallet address to a known label (e.g. 'Binance 14', 'Jump Trading', 'a16z fund 2', 'Wintermute OTC').", "parameters": { "type": "object", "properties": {"address": {"type": "string"}}, "required": ["address"], }, }, } IS_CEX_ADDRESS = { "type": "function", "function": { "name": "is_cex_address", "description": "Return whether the address is a known centralized exchange hot or cold wallet, and which exchange.", "parameters": { "type": "object", "properties": {"address": {"type": "string"}}, "required": ["address"], }, }, } CLASSIFY_MOVEMENT = { "type": "function", "function": { "name": "classify_movement", "description": "Classify a single transaction into one of: CEX_INFLOW, CEX_OUTFLOW, OTC_SETTLEMENT, DEX_SWAP, BRIDGE_OUT, BRIDGE_IN, WALLET_REBALANCE, UNKNOWN.", "parameters": { "type": "object", "properties": { "tx": { "type": "object", "description": "Raw transaction object including from, to, value, input data, and chain.", }, }, "required": ["tx"], }, }, } IS_DEX_SWAP = { "type": "function", "function": { "name": "is_dex_swap", "description": "Return whether a transaction's `to` field matches a known DEX router (Uniswap V2/V3/V4, Jupiter, Raydium, Aerodrome).", "parameters": { "type": "object", "properties": { "tx": {"type": "object"}, "dex_routers": { "type": "array", "items": {"type": "string"}, }, }, "required": ["tx", "dex_routers"], }, }, } IS_BRIDGE_TX = { "type": "function", "function": { "name": "is_bridge_tx", "description": "Return whether a transaction interacts with a known canonical bridge (Wormhole, LayerZero, Across, Stargate, Base bridge).", "parameters": { "type": "object", "properties": { "tx": {"type": "object"}, "bridge_contracts": { "type": "array", "items": {"type": "string"}, }, }, "required": ["tx", "bridge_contracts"], }, }, } POST_WHALE_ALERT = { "type": "function", "function": { "name": "post_whale_alert", "description": "Post a formatted whale alert to the configured Slack and Discord webhooks.", "parameters": { "type": "object", "properties": { "text": {"type": "string"}, "severity": { "type": "string", "enum": ["INFO", "WATCH", "ALERT", "CRITICAL"], }, "ticker": {"type": "string"}, }, "required": ["text", "severity", "ticker"], }, }, } CHAIN_TOOLS = [ FETCH_RECENT_BLOCK, GET_WALLET_TRANSACTIONS, LOOKUP_WALLET_LABEL, IS_CEX_ADDRESS, IS_DEX_SWAP, IS_BRIDGE_TX, ] CLASSIFIER_TOOLS = [CLASSIFY_MOVEMENT, LOOKUP_WALLET_LABEL, IS_CEX_ADDRESS] ALERT_TOOLS = [POST_WHALE_ALERT] ``` ## Step 3: Define the Concurrent Per-Chain Agents Each chain monitor runs on `gpt-4.1-mini` — fast and cheap is the only thing that matters when you are firing this swarm every 12 seconds. The Movement Classifier runs on `grok-4` for its real-time bias and willingness to commit to a classification under uncertainty. The Alert Generator runs on `claude-sonnet-4.5` because the natural-language quality of the Slack message is what makes the desk actually read it. ```python theme={null} CHAIN_MONITOR_PROMPT = ( "You are an on-chain whale monitor for {chain}. " "For the given block, pull the transactions involving any address in the " "top-100 whale list. For each tx, return a structured row with: " "from, to, value_native, value_usd_estimate, raw_input_summary. " "Use the available tools to enrich with wallet labels and CEX/bridge/DEX flags. " "Output strict JSON. Do not editorialize. Speed matters — your output feeds the classifier " "in the same swarm call." ) MOVEMENT_CLASSIFIER_PROMPT = ( "You are the Movement Classifier. You receive per-chain whale tx rows from four monitors " "running concurrently. For each row, call classify_movement and assign one of: " "CEX_INFLOW, CEX_OUTFLOW, OTC_SETTLEMENT, DEX_SWAP, BRIDGE_OUT, BRIDGE_IN, " "WALLET_REBALANCE, UNKNOWN. " "Cross-correlate across chains — a BRIDGE_OUT on ETH and a matching BRIDGE_IN on BASE " "in the same swarm window should be linked. Output strict JSON, one row per movement. " "Bias toward committing — UNKNOWN is the last resort." ) ALERT_GENERATOR_PROMPT = ( "You are the Alert Generator. You receive classified whale movements from the Movement " "Classifier. For each one, decide severity (INFO/WATCH/ALERT/CRITICAL) based on " "value_usd, target_label, and movement_type. Write a one-line, desk-readable Slack message " "in this style: " "':whale: ALERT — 1,250 BTC moved from Tether Treasury 7 to Binance 14 (~$92M, BRIDGE_IN, block 879314)'. " "Then call post_whale_alert. Be precise, be brief, never speculate on price impact." ) def build_whale_swarm(block_targets: dict[str, int]) -> dict: """block_targets maps chain → block number to inspect, e.g. {'ETH': 21000123, ...}""" chain_agents = [] for chain, block_num in block_targets.items(): chain_agents.append({ "agent_name": f"{chain} Whale Monitor", "description": f"Pulls whale-relevant transactions on {chain} for a specific block.", "system_prompt": CHAIN_MONITOR_PROMPT.format(chain=chain), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.1, "tools_list_dictionary": CHAIN_TOOLS, "mcp_url": MCP_URLS[chain], }) classifier = { "agent_name": "Movement Classifier", "description": "Classifies whale movements across chains in real time.", "system_prompt": MOVEMENT_CLASSIFIER_PROMPT, "model_name": "grok-4", "role": "worker", "max_loops": 1, "max_tokens": 6144, "temperature": 0.2, "tools_list_dictionary": CLASSIFIER_TOOLS, } alert_generator = { "agent_name": "Alert Generator", "description": "Writes severity-scored Slack/Discord alerts.", "system_prompt": ALERT_GENERATOR_PROMPT, "model_name": "claude-sonnet-4.5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": ALERT_TOOLS, } return { "name": "On-Chain Whale Tracker", "description": "Per-chain concurrent monitors → classifier → alerter, one swarm call per block.", "swarm_type": "ConcurrentWorkflow", "max_loops": 1, "task": ( "For the given block on each chain, identify and classify every whale-relevant " "transaction and emit structured alerts. Block targets: " + json.dumps(block_targets) ), "agents": chain_agents + [classifier, alert_generator], } ``` <Note> The classifier and alert generator are inside the same `ConcurrentWorkflow` call as the chain monitors. The swarm scheduler still gives the chain monitors their parallel fan-out — the later-stage agents simply run with the aggregated outputs as input context. If you want a strict pipeline (fan-out then sequential), wrap the chain monitors in an inner `ConcurrentWorkflow` and the classifier/alerter in an outer `SequentialWorkflow`. For a hot loop you want the simpler single-swarm shape. </Note> ## Step 4: Process One Block End-to-End Before flipping on the watcher, pin to a known block on each chain and dry-run the swarm. This validates MCP wiring, tool schemas, and the classifier's commitment behavior on a static input. ```python theme={null} def run_one_block(block_targets: dict[str, int]) -> dict: payload = build_whale_swarm(block_targets) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=180, ) response.raise_for_status() return response.json() # Replay a known whale block result = run_one_block({ "ETH": 21000123, "BTC": 879314, "SOL": 301288010, "BASE": 22001456, }) for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600]) print(f"\nSwarm cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Wall time: {result['execution_time']:.2f}s") ``` If wall time on the replay exceeds ETH block time (12 seconds), you have a latency problem and the watcher will fall behind under live load. Lower `max_tokens` on the chain monitors and tighten the classifier prompt before going live. ## Step 5: The Continuous Block Watcher This is the loop that bills. Every \~12 seconds — ETH block time, the slowest of the four — fire a fresh swarm against the latest block on each chain. ```python theme={null} def get_latest_blocks() -> dict[str, int]: """Return the most recent block number on each chain via your RPC layer.""" # Implementation depends on your RPC client; sketch: return { "ETH": rpc_eth.block_number(), "BTC": rpc_btc.block_height(), "SOL": rpc_sol.slot(), "BASE": rpc_base.block_number(), } def fire_swarm(block_targets: dict[str, int]) -> None: payload = build_whale_swarm(block_targets) requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=60, ) def whale_watcher_loop() -> None: last_seen = {"ETH": 0, "BTC": 0, "SOL": 0, "BASE": 0} while True: latest = get_latest_blocks() # Only fire if at least one chain has advanced if any(latest[c] > last_seen[c] for c in latest): fire_swarm(latest) last_seen = latest time.sleep(12) # ETH block time pacing if __name__ == "__main__": whale_watcher_loop() ``` The math is brutal: * 12-second cadence → **300 calls/hour**, **7,200 calls/day** * Free tier caps are **100/minute**, **350/hour**, **1,200/day** — the per-day cap is breached in **4 hours** * Paid tiers (Pro, Ultra, Premium) share **2,000/minute**, **10,000/hour**, **100,000/day**, which holds this loop * A paid tier also gives you the execution traces you need to debug missed blocks <Info> Live whale tracking is a Premium workload by construction. If you try to run this loop on Free you will hit 429s, miss blocks, and have no observability to tell which blocks you missed. See [Rate Limits](/docs/documentation/resources/ratelimits) for the per-tier numbers and upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Info> ## Step 6: The Alert Output Schema The Alert Generator emits structured rows alongside the Slack post — persist these to your warehouse so you can correlate alerts against spot moves later and grade the classifier. ```json theme={null} { "chain": "ETH", "block": 21000123, "whale_address": "0xab5801a7d398351b8be11c439e05c5b3259aec9b", "movement_type": "CEX_INFLOW", "value_usd": 92400000, "target_address": "0x28c6c06298d514db089934071355e5743bf21d60", "target_label": "Binance 14", "severity": "CRITICAL", "narrative": "1,250 BTC moved from a long-dormant cold wallet to Binance hot wallet 14 (~$92M). Last activity on source wallet: 187 days ago." } ``` A simple persistence pattern: ```python theme={null} def persist_alerts(swarm_response: dict, path: str = "whale_alerts.jsonl") -> None: alerts_block = next( (o["content"] for o in swarm_response.get("output", []) if "Alert Generator" in o.get("role", "")), None, ) if not alerts_block: return if isinstance(alerts_block, list): alerts_block = " ".join(str(c) for c in alerts_block) # Alerts arrive as JSON lines from the Alert Generator with open(path, "a") as f: for line in str(alerts_block).splitlines(): line = line.strip() if line.startswith("{") and line.endswith("}"): f.write(line + "\n") ``` ## Real Cost vs. Whale Alert Service Subscriptions | Stack | Monthly cost | What you actually get | | --------------------------------------------------------------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------ | | **This stack** (gpt-4.1-mini chains + grok-4 classifier + sonnet-4.5 alerter, night-mode discount on quiet 02:00–06:00 UTC) | **\~\$750/mo** (\~\$25/day) | Programmable layer you own, four chains, custom whale list, structured outputs to your warehouse | | Retail whale-alert Twitter / Telegram services | \$50 – \$500/mo | Read-only Twitter feed, no classification, no programmatic access | | Nansen Alpha (single chain) | \$1,500/mo | Best-in-class labels, read-only dashboard, no programmable layer | | Arkham Intelligence Pro | \$1,000/mo | Strong labels, dashboard + alerts, no per-block classification | | Building this in-house with engineers | \$40,000+/mo | One mid backend + one ML engineer plus infra; what you would actually do without this | Night-mode tip: between 02:00 and 06:00 UTC most chains are quiet. Drop the watcher to a 60-second cadence in that window — call cost falls \~5x and you almost never miss meaningful flow. The point is not that this is cheaper than a Twitter bot. The point is that a Twitter bot is read-only. This is a programmable layer with structured outputs that route into your own systems — execution, risk, research database — at whale-feed latency. ## Next Steps * See [Crypto Quant Agent](/docs/examples/examples/crypto-quant-agent) for the single-agent quant analyst that consumes these alerts as a signal stream * See [AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) for the hierarchical pattern when you want a PM agent grading the whale alerts against a fundamental thesis * Read [MCP Integration](/docs/documentation/capabilities/mcp_integration) for the full Alchemy / Helius / mempool MCP wiring * Check [Rate Limits](/docs/documentation/resources/ratelimits) before going live — the per-tier caps decide what cadence you can sustain # Crypto Quant Agent Source: https://docs.swarms.ai/docs/examples/examples/crypto-quant-agent A domain-specific single agent for quantitative cryptocurrency market analysis. ## What This Example Shows * A focused single-agent build for a specialized domain (crypto quant analysis) * How to write a long, structured `system_prompt` that constrains output to quantitative reasoning * How to wire the agent up to live market data via MCP (optional) <Info> This is the same pattern as the [Single Agent Overview](/docs/examples/examples/agent-overview), specialized for crypto. The same shape extends to any analyst domain — credit risk, equity research, intelligence triage, claims review. </Info> ## Step 1: Setup ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Agent The `system_prompt` is where domain expertise lives. Be specific about responsibilities and the kind of reasoning you want. ```python theme={null} def run_crypto_analyst(task: str) -> dict: payload = { "agent_config": { "agent_name": "Crypto Quant Analyst", "description": ( "Quantitative analyst specializing in cryptocurrency markets " "and trading strategies." ), "system_prompt": ( "You are a Crypto Quant Analyst with deep expertise in " "quantitative analysis of cryptocurrency markets. Analyze crypto " "market data, identify trading patterns, calculate risk metrics, " "and develop data-driven trading strategies.\n\n" "Key responsibilities:\n" "- Perform technical analysis on cryptocurrency price movements\n" "- Calculate volatility, correlation, and risk metrics\n" "- Identify market trends and trading opportunities\n" "- Analyze trading volumes and market liquidity\n" "- Provide quantitative insights for portfolio management\n" "- Suggest risk-adjusted trading strategies\n\n" "Always support your analysis with quantitative data and " "statistical reasoning. Consider market cap, trading volume, " "price volatility, asset correlation, and technical indicators." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, "task": task, } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=120, ) response.raise_for_status() return response.json() ``` ## Step 3: Run It ```python theme={null} if __name__ == "__main__": result = run_crypto_analyst("Analyze Bitcoin (BTC).") print(json.dumps(result, indent=2)) ``` ## Adding Live Market Data via MCP To give the agent access to real-time market data, attach an MCP server URL. Any OKX/Binance/CoinGecko MCP server works as long as it exposes the right tools. ```python theme={null} payload = { "agent_config": { # ...existing fields... "mcp_url": "http://your-okx-mcp:8001/sse", }, "task": task, } ``` See [MCP Integration](/docs/examples/examples/mcp-integration) for a full walkthrough of MCP wiring and tool discovery. <Note> The `temperature: 0.3` setting is intentional. Analytical and quantitative agents benefit from low-temperature outputs — they should be consistent and deterministic. Creative agents (copywriters, ideators) want higher temperatures. Pick the temperature to match the *kind of reasoning* you need, not the difficulty of the task. </Note> ## Build Your Own Domain Agent Replace the `system_prompt` and `task` to retarget: | Domain | system\_prompt focus | Suggested temperature | | ----------------------- | ----------------------------------------------------------- | --------------------- | | **Credit risk** | Default probability, debt service ratios, covenant analysis | 0.2 | | **Equity research** | DCF, multiples, peer comp, catalysts | 0.3 | | **Threat intel triage** | IOCs, attribution, severity scoring | 0.2 | | **Claims review** | Coverage match, fraud signals, payout calc | 0.2 | | **Marketing copy** | Tone, hook, CTA variants | 0.8 | Everything else stays the same — same API, same response shape, same billing. # Build a Customer Support Swarm: Triage, Reply, Escalate Source: https://docs.swarms.ai/docs/examples/examples/customer-support-swarm A HierarchicalSwarm that classifies every inbound ticket, drafts a customer-ready reply, and routes the risky ones to a human — wired to Intercom or Zendesk in under an afternoon. ## What This Example Shows * A `HierarchicalSwarm` with a Triage Manager routing tickets to one of five specialists: Billing, Technical, Account, Product Liaison, Retention * A Quality Reviewer agent that scores every draft for tone and confidence, then sets an escalation flag * A complete `/v1/swarm/completions` call for a realistic ticket — subject, body, and suggested next action returned as a structured reply * A Flask webhook that catches new Intercom conversations, runs the swarm, and either auto-replies via the Intercom REST API or drops the ticket into a human queue * A `/v1/swarm/batch/completions` pattern for clearing a 500-ticket overnight backlog for about \$50 * The cost math: \~\$0.10 per ticket vs. \~\$1.50 for a fully loaded tier-1 agent <Info> This tutorial uses `HierarchicalSwarm` and `/v1/swarm/batch/completions` — both included on every paid Swarms tier. For production-volume webhook traffic and overnight batches above a few thousand tickets, upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account) for the parallel execution and rate-limit headroom you need. </Info> ## Why This Matters A fully loaded tier-1 support agent runs \~\$50K/yr and clears about 30 tickets a day. A swarm running on this stack handles 30,000 tickets a day for under \$200. The job is not to fire the support team — it is to put a customer-ready, on-brand drafted reply in front of your humans so they approve-and-send in five seconds instead of writing from scratch in five minutes. That single shift takes your team from drowning in queue to ahead of SLA, and it does the boring 80% of tickets autonomously so the humans get their afternoon back for the cases that actually need them. Every SaaS company on Earth has this problem and almost none of them have shipped a real fix. ## The Architecture ``` Incoming Ticket | v +-------------------+ | Triage Manager | <- classifies + routes | (coordinator) | +-------------------+ | +---------------+-----+-----+---------------+--------------+ | | | | | v v v v v +---------+ +-----------+ +---------+ +-----------+ +-----------+ | Billing | | Technical | | Account | | Product | | Retention | |Specialist| | Support | | Manager | | Liaison | |Specialist | +---------+ +-----------+ +---------+ +-----------+ +-----------+ | | | | | +---------------+-----+-----+---------------+--------------+ | v +-------------------+ | Quality Reviewer | <- tone + confidence + escalate +-------------------+ | +-------------+--------------+ | | v v Auto-send reply Human review queue (Intercom REST) (escalation flag = true) ``` ## Step 1: Setup Install the dependencies and grab your API key from [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ```bash theme={null} pip install requests flask python-dotenv export SWARMS_API_KEY="your-api-key-here" export INTERCOM_ACCESS_TOKEN="your-intercom-token-here" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") INTERCOM_TOKEN = os.getenv("INTERCOM_ACCESS_TOKEN") BASE_URL = "https://api.swarms.world" if not API_KEY: raise ValueError("SWARMS_API_KEY environment variable is required") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Triage + Specialist + Quality Team Seven agents. The Triage Manager owns routing. Each specialist drafts a customer-ready reply in a strict format the Quality Reviewer can grade. The Quality Reviewer decides whether the draft auto-sends or goes to a human. ```python theme={null} TRIAGE_PROMPT = ( "You are the Triage Manager for a SaaS customer support team. " "Given an inbound ticket, you do two things:\n\n" "1. Classify the ticket into exactly ONE of these categories:\n" " - BILLING (invoices, refunds, plan changes, payment failures)\n" " - TECHNICAL (bugs, errors, integrations, performance, API issues)\n" " - ACCOUNT (login, SSO, seats, permissions, org settings)\n" " - PRODUCT (feature requests, how-do-I, roadmap questions)\n" " - RETENTION (cancellation, downgrade intent, churn signals, frustration)\n\n" "2. Delegate to the matching specialist with a one-paragraph briefing that " "extracts the customer's name, plan tier, account ID if present, and the " "single thing they need.\n\n" "Be decisive. Never assign to more than one specialist. If the ticket spans " "categories, pick the dominant one and note the secondary in the briefing." ) SPECIALIST_OUTPUT_FORMAT = ( "Your reply MUST follow this exact format:\n\n" "SUBJECT: <re: original subject>\n" "BODY:\n" "<the customer-ready reply, signed off as the support team>\n" "SUGGESTED_NEXT_ACTION: <one line — e.g. 'refund $49 via Stripe', " "'create JIRA bug', 'no action needed', 'schedule retention call'>\n" "INTERNAL_NOTES: <one line for the human reviewer — context that does NOT go to the customer>\n\n" "Tone: warm, direct, no corporate filler. Never apologize more than once. " "Never promise timelines you can't keep. Always reference the original ticket ID." ) BILLING_PROMPT = ( "You are a Billing Specialist. Customers come to you for invoices, refunds, " "plan changes, payment failures, and proration questions. You know Stripe, " "annual vs. monthly mechanics, dunning, and ACH timing. " "Draft a reply that resolves the issue or names the exact next step. " f"{SPECIALIST_OUTPUT_FORMAT}" ) TECHNICAL_PROMPT = ( "You are a Technical Support Engineer. Customers come to you with bugs, " "error messages, API issues, integration failures, and performance problems. " "Ask for logs, request IDs, and reproduction steps only when truly needed — " "default to giving the answer if the ticket already contains enough signal. " f"{SPECIALIST_OUTPUT_FORMAT}" ) ACCOUNT_PROMPT = ( "You are an Account Manager handling login, SSO, seat management, permissions, " "and organization settings. You know SAML, SCIM, role hierarchies, and the " "common reasons a user is locked out. Be direct and unblock the customer. " f"{SPECIALIST_OUTPUT_FORMAT}" ) PRODUCT_PROMPT = ( "You are a Product Liaison handling feature requests, how-do-I questions, " "and roadmap inquiries. Acknowledge the request, point to existing docs or " "workarounds, and capture the request cleanly in INTERNAL_NOTES so product " "can triage it later. Never commit to ship dates. " f"{SPECIALIST_OUTPUT_FORMAT}" ) RETENTION_PROMPT = ( "You are a Retention Specialist. The customer is signaling cancellation, " "downgrade, or serious frustration. Your job is NOT to argue them out of it — " "it is to acknowledge the friction, name a concrete path to fix it, and offer " "the right save play (pause, downgrade tier, credit, success call) for the " "situation. If the case is already lost, write a clean offboarding reply. " f"{SPECIALIST_OUTPUT_FORMAT}" ) QUALITY_REVIEWER_PROMPT = ( "You are the Quality Reviewer. You read the specialist's drafted reply and " "the original ticket, then return a STRICT JSON object with these keys only:\n\n" "{\n" ' "final_subject": "<the subject line to send>",\n' ' "final_body": "<the body to send, edited for tone if needed>",\n' ' "suggested_next_action": "<carried through from the specialist>",\n' ' "category": "BILLING | TECHNICAL | ACCOUNT | PRODUCT | RETENTION",\n' ' "confidence": <float 0.0-1.0>,\n' ' "escalate_to_human": <true | false>,\n' ' "escalation_reason": "<one sentence, or empty string>"\n' "}\n\n" "Escalate to a human if ANY of the following are true:\n" "- Confidence below 0.75\n" "- Refund amount mentioned exceeds $200\n" "- Any mention of legal action, GDPR, HIPAA, SOC2, data breach, or media\n" "- Customer is on Enterprise tier\n" "- Retention category with HIGH churn signal\n" "- Reply contains a commitment to a timeline or dollar amount the AI cannot verify\n\n" "Output JSON only. No prose, no markdown fences." ) def build_support_swarm(ticket_payload: str) -> dict: return { "name": "Customer Support Swarm", "description": "Triage Manager routing to specialists with a Quality Reviewer gate.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ticket_payload, "agents": [ { "agent_name": "Triage Manager", "description": "Coordinator — classifies the ticket and delegates to the right specialist.", "system_prompt": TRIAGE_PROMPT, "model_name": "claude-sonnet-4.5", "role": "coordinator", "max_loops": 1, "max_tokens": 2048, "temperature": 0.1, }, { "agent_name": "Billing Specialist", "description": "Invoices, refunds, plan changes, payment failures.", "system_prompt": BILLING_PROMPT, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Technical Support Engineer", "description": "Bugs, errors, API, integrations, performance.", "system_prompt": TECHNICAL_PROMPT, "model_name": "claude-haiku-4.5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Account Manager", "description": "Login, SSO, seats, permissions, org settings.", "system_prompt": ACCOUNT_PROMPT, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Product Liaison", "description": "Feature requests, how-do-I, roadmap.", "system_prompt": PRODUCT_PROMPT, "model_name": "grok-4", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Retention Specialist", "description": "Cancellation, downgrade intent, churn signals.", "system_prompt": RETENTION_PROMPT, "model_name": "claude-haiku-4.5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, { "agent_name": "Quality Reviewer", "description": "Final tone, confidence, and escalation gate.", "system_prompt": QUALITY_REVIEWER_PROMPT, "model_name": "claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.0, }, ], } ``` <Note> The Triage Manager runs on `claude-sonnet-4.5` because misrouting cascades into the wrong specialist and burns the whole pipeline. Specialists run on cheaper models (`gpt-4.1-mini`, `claude-haiku-4.5`, `grok-4`) — they are doing template-shaped writing and the cost difference is what keeps this near \$0.10/ticket. The Quality Reviewer steps up to `claude-opus-4-8` because the escalation decision is load-bearing. </Note> ## Step 3: Process a Single Ticket Build a realistic ticket, post it to `/v1/swarm/completions`, and pull the Quality Reviewer's JSON out of the response. ````python theme={null} TICKET = """ TICKET ID: TICK-48219 CUSTOMER: Maria Chen (maria@northwindlogistics.com) PLAN: Growth ($299/mo, 14 months active) CHANNEL: Email SUBJECT: Charged twice for October — please refund BODY: Hi team, I just noticed two charges of $299 on October 3rd from Swarms. One was the regular monthly renewal and the other looks like a duplicate. My card ending in 4242 was hit twice. Can you refund the duplicate and confirm the next billing date? This is the second time this has happened — last time was in July and Sarah on your team fixed it within an hour. I'd appreciate a quick turnaround, we're closing our quarter. Thanks, Maria """ def run_support_swarm(ticket: str) -> dict: payload = build_support_swarm(ticket) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() def extract_quality_review(swarm_result: dict) -> dict: """Pull the Quality Reviewer's JSON out of the swarm response.""" for output in swarm_result.get("output", []): if "Quality Reviewer" in output.get("role", ""): content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) text = str(content).strip() # Strip optional markdown fences if the model added them if text.startswith("```"): text = text.strip("`") if text.startswith("json"): text = text[4:] try: return json.loads(text.strip()) except json.JSONDecodeError: return { "escalate_to_human": True, "escalation_reason": "Quality Reviewer output failed to parse", "confidence": 0.0, "final_body": "", } return {"escalate_to_human": True, "escalation_reason": "No reviewer output", "confidence": 0.0} result = run_support_swarm(TICKET) review = extract_quality_review(result) print(json.dumps(review, indent=2)) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ```` The Quality Reviewer's JSON is the single object your application needs. `escalate_to_human` is the only field that decides what happens next — every downstream branch reads from there. ## Step 4: Wire It to Intercom (or Zendesk) via Webhook Drop the swarm behind a Flask webhook. Intercom POSTs every new conversation to your endpoint, you run the swarm, and you either reply via the Intercom REST API or assign the conversation to a human teammate based on the escalation flag. ```python theme={null} from flask import Flask, request, jsonify app = Flask(__name__) INTERCOM_BASE = "https://api.intercom.io" INTERCOM_HEADERS = { "Authorization": f"Bearer {INTERCOM_TOKEN}", "Accept": "application/json", "Content-Type": "application/json", "Intercom-Version": "2.11", } # Set this to the teammate ID of your human escalation queue / team inbox HUMAN_QUEUE_TEAMMATE_ID = os.getenv("INTERCOM_HUMAN_QUEUE_ID") def post_intercom_reply(conversation_id: str, body: str) -> dict: """Send a public reply to an Intercom conversation as the support bot.""" url = f"{INTERCOM_BASE}/conversations/{conversation_id}/reply" response = requests.post( url, headers=INTERCOM_HEADERS, json={ "message_type": "comment", "type": "admin", "admin_id": os.getenv("INTERCOM_BOT_ADMIN_ID"), "body": body, }, timeout=30, ) response.raise_for_status() return response.json() def assign_to_human_queue(conversation_id: str, internal_note: str) -> dict: """Leave an internal note with the swarm's draft, then assign to the human team.""" url = f"{INTERCOM_BASE}/conversations/{conversation_id}/parts" requests.post( url, headers=INTERCOM_HEADERS, json={ "message_type": "note", "type": "admin", "admin_id": os.getenv("INTERCOM_BOT_ADMIN_ID"), "body": internal_note, }, timeout=30, ) assign_url = f"{INTERCOM_BASE}/conversations/{conversation_id}/parts" response = requests.post( assign_url, headers=INTERCOM_HEADERS, json={ "message_type": "assignment", "type": "admin", "admin_id": os.getenv("INTERCOM_BOT_ADMIN_ID"), "assignee_id": HUMAN_QUEUE_TEAMMATE_ID, }, timeout=30, ) response.raise_for_status() return response.json() @app.post("/webhook/intercom") def intercom_webhook(): payload = request.get_json(force=True) # Intercom sends conversation.user.created for new inbound conversations if payload.get("topic") != "conversation.user.created": return jsonify({"status": "ignored"}), 200 conv = payload["data"]["item"] conversation_id = conv["id"] customer_email = conv["source"]["author"].get("email", "unknown") subject = conv["source"].get("subject", "(no subject)") body = conv["source"]["body"] ticket_payload = ( f"TICKET ID: {conversation_id}\n" f"CUSTOMER: {customer_email}\n" f"SUBJECT: {subject}\n\n" f"BODY:\n{body}\n" ) swarm_result = run_support_swarm(ticket_payload) review = extract_quality_review(swarm_result) if review.get("escalate_to_human"): internal_note = ( f"<b>Swarm draft (NOT sent — escalated)</b><br>" f"<b>Reason:</b> {review.get('escalation_reason', 'unknown')}<br>" f"<b>Confidence:</b> {review.get('confidence', 0.0):.2f}<br>" f"<b>Category:</b> {review.get('category', 'unknown')}<br>" f"<b>Suggested action:</b> {review.get('suggested_next_action', '')}<br><br>" f"<b>Draft body:</b><br>{review.get('final_body', '')}" ) assign_to_human_queue(conversation_id, internal_note) return jsonify({"status": "escalated", "review": review}), 200 post_intercom_reply(conversation_id, review["final_body"]) return jsonify({"status": "auto_replied", "review": review}), 200 if __name__ == "__main__": app.run(host="0.0.0.0", port=8080) ``` <Info> For Zendesk, swap the Intercom calls for the equivalent endpoints — `POST /api/v2/tickets/{id}/comments` for the reply and `PUT /api/v2/tickets/{id}.json` with `{"ticket": {"assignee_id": <human_id>}}` for the escalation. The swarm layer does not change. </Info> ## Step 5: Batch Mode for Existing Backlog When the team comes back from a long weekend with 500 tickets stacked up, you do not run the webhook 500 times — you fan them out through `/v1/swarm/batch/completions` and clear the queue overnight. ```python theme={null} def clear_backlog(tickets: list[str], chunk_size: int = 50) -> list[dict]: """Run the support swarm across a list of tickets via batch completions.""" all_reviews: list[dict] = [] total_cost = 0.0 for start in range(0, len(tickets), chunk_size): chunk = tickets[start : start + chunk_size] payloads = [build_support_swarm(t) for t in chunk] print(f"Submitting tickets {start}..{start + len(chunk) - 1}") response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payloads, timeout=1800, ) response.raise_for_status() results = response.json() for r in results: all_reviews.append(extract_quality_review(r)) total_cost += r.get("usage", {}).get("billing_info", {}).get("total_cost", 0) print(f"Cleared {len(all_reviews)} tickets for ${total_cost:.2f}") return all_reviews # backlog is your list of raw ticket strings from Intercom export, Zendesk dump, etc. # reviews = clear_backlog(backlog) # auto_send = [r for r in reviews if not r.get("escalate_to_human")] # human_queue = [r for r in reviews if r.get("escalate_to_human")] ``` A 500-ticket backlog at this swarm shape runs about \$50 end-to-end and finishes in the time it takes to refill the coffee pot. The auto-send list goes straight to Intercom, the human queue lands in your inbox with the draft and escalation reason already attached. ## Real Cost vs. Tier-1 Support | Scenario | Cost per ticket | Cost per month (10K tickets) | Throughput | | ------------------------------------------------------------------ | --------------- | ---------------------------- | -------------------- | | Customer support swarm (claude-sonnet-4.5 + mini-tier specialists) | \~\$0.10 | \~\$1,000 | minutes per batch | | Tier-1 agent (fully loaded \~\$50k, \~30/day) | \~\$1.50 | \~\$15,000 | bounded by headcount | | BPO outsourced floor | \~\$0.80–\$2.50 | \~\$8,000–\$25,000 | hours to days | Your humans are not gone — they are reviewing the 10-20% of tickets the Quality Reviewer flagged, plus the ones that came back with follow-up questions. The swarm took the 30,000 routine tickets off their plate, which is the entire point. A tier-1 floor of ten people now does the work of a floor of fifty, with shorter response times and a fully auditable trail per ticket. ## Guardrails These rules belong in code, not in the prompt — the prompt is a soft constraint, the code is hard. * **Never auto-send for refunds above \$X.** Hard-cap it. Read the dollar amount out of `suggested_next_action` with a regex and force escalation if it exceeds your finance team's pre-approved threshold. * **Never auto-send for legal, compliance, or media topics.** Match on keywords (`lawsuit`, `attorney`, `GDPR`, `HIPAA`, `breach`, `press`, `journalist`) and force escalation regardless of confidence. * **Always include the original ticket ID in the reply.** Customers reference it, your support team searches by it, your audit log requires it. The specialist prompts include it but verify in code before sending. * **Rate-limit auto-replies per customer.** If you have already auto-sent two replies on a thread, the third one is escalated by default — a customer who is still responding usually needs a human. * **Log every swarm decision.** Persist the Quality Reviewer JSON, the specialist who drafted, and the model usage to your warehouse. The first time you debate "is the swarm getting better or worse," that table is the only thing that matters. * **Run a shadow week before going live.** Send every ticket through the swarm, drop every result into an internal note, never auto-send. Your support leads grade a sample of 200 drafts. Ship when the approval rate clears the bar you set. ## Next Steps * See the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) for the director-and-workers pattern in more depth * Read [Tools in Swarms](/docs/examples/examples/tools-in-swarms) to give the Billing Specialist a real Stripe refund tool and the Technical Engineer a real log-search tool * Browse [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) for the underlying batch endpoint mechanics and rate-limit guidance # Daily AI Briefings in Slack: News, Stocks, and Calendar at 7AM Source: https://docs.swarms.ai/docs/examples/examples/daily-slack-ai-briefings A ~50-line ConcurrentWorkflow swarm that posts your morning news, market open, and calendar to Slack every weekday at 7AM via cron. ## What This Example Shows * A `ConcurrentWorkflow` swarm with three agents running in parallel — News Curator, Market Watcher, Calendar Briefer * How to fan a swarm's outputs into a Slack `blocks` payload via an incoming webhook * A real cron schedule — `0 7 * * 1-5` — that ships a useful briefing to your team channel before standup * The full pipeline in roughly 55 lines of Python with `requests` and `python-dotenv` only * A genuine ship-it-before-coffee pattern: 60 seconds to set up env vars, 5 minutes to install the cron <Info> Get a free Swarms API key in 1 minute at [swarms.world](https://swarms.world). Get a free Slack incoming webhook URL in 2 minutes from your workspace's app directory ("Incoming Webhooks" → "Add to Slack" → pick a channel → copy the URL). Drop the cron line on any always-on box in 5 minutes. Total time-to-first-briefing: under 10 minutes. </Info> ## Why You'll Actually Use This The briefing has the three sections you actually want before coffee: how the market opened in red or green, the top stories that touch your world, and what's already booked on your calendar. It lands in Slack so you can't miss it, your team sees the same context you do, and once Monday's briefing shows up your morning quietly depends on it. That's the whole pitch — useful enough that you forget it's running. ## The Output Here's what shows up in your Slack channel at 7:00:01 every weekday: ``` :sunrise: *Morning Briefing — Monday, May 26, 2026* > Markets opening green on soft CPI; OpenAI ships a new model; you have 4 meetings starting at 9:30. *:chart_with_upwards_trend: Market Watcher* - S&P 500 futures +0.42% pre-market; 10Y yield at 4.31% - NVDA +1.8% on supply-chain note; TSLA -0.9% on delivery rumor - Bitcoin holding $67.2K; ETH at $3,510 *:newspaper: News Curator* - OpenAI announces GPT-5.5 with 2M-token context (TechCrunch) - Fed minutes hint at September cut; CPI prints 2.4% YoY (Reuters) - Anthropic raises $4B Series E at $40B post (Bloomberg) *:calendar: Calendar Briefer* - 09:30 — Weekly eng sync (45m) - 11:00 — Customer call: Acme Corp renewal (30m) - 14:00 — 1:1 with Priya (30m) - 16:30 — Investor update prep (60m) ``` ## The Architecture ``` ┌──────────────────────┐ │ ConcurrentWorkflow │ └──────────┬───────────┘ │ fan-out (parallel) ┌────────────────────┼────────────────────┐ │ │ │ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │News Curator │ │Market Watcher│ │Calendar │ │ │ │ │ │Briefer │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └────────────────────┼────────────────────┘ │ fan-in ┌──────────▼───────────┐ │ build_slack_blocks() │ └──────────┬───────────┘ │ ┌──────────▼───────────┐ │ Slack Incoming Hook │ └──────────────────────┘ ``` One swarm call, three agents in parallel, one synthesizer function, one webhook POST. ## Step 1: Setup (60 seconds) ```bash theme={null} pip install requests python-dotenv ``` Create a `.env` next to your script: ```bash theme={null} SWARMS_API_KEY=sk-... SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T000/B000/XXXX CALENDAR_TODAY="09:30 Weekly eng sync (45m); 11:00 Acme renewal (30m); 14:00 1:1 with Priya (30m); 16:30 Investor update prep (60m)" ``` <Note> `CALENDAR_TODAY` is a simple string you can pipe in from `icalBuddy`, a Google Calendar export, or a quick `gcalcli agenda` call. The Calendar Briefer agent reformats whatever you hand it — no calendar API integration required for v1. </Note> ## Step 2: Define Three Concurrent Agents Each system prompt is under four sentences to keep the output Slack-shaped instead of essay-shaped. ```python theme={null} AGENTS = [ { "agent_name": "News Curator", "system_prompt": ( "You are a morning news curator. Surface the 3 most important stories " "from the last 24 hours relevant to AI, tech, and macro markets. " "Output exactly 3 bullets, each one line, with the source in parentheses. " "No preamble, no closing remarks." ), "model_name": "gemini-2.5-pro", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Market Watcher", "system_prompt": ( "You are a pre-market briefer. Report S&P 500 futures, 10Y yield, " "two notable single-stock moves, and BTC/ETH levels. " "Output 3 bullets max, each one line, numbers first. " "No commentary, no disclaimers." ), "model_name": "grok-4", "max_loops": 1, "temperature": 0.2, }, { "agent_name": "Calendar Briefer", "system_prompt": ( "You are a calendar briefer. Reformat the user's raw calendar string " "into clean bullets sorted by start time, format 'HH:MM — Title (duration)'. " "One bullet per meeting. No summary line, no advice." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "temperature": 0.1, }, ] ``` <Note> There's no per-agent live-search toggle for agents inside a `/v1/swarm/completions` request — `AgentSpec` has no `search_enabled` field, so setting one is a silent no-op. News Curator and Market Watcher answer from the underlying model's own training knowledge here, not a live feed. If you need guaranteed real-time data, either wire a real tool (`tools_list_dictionary` or `mcp_url`/`mcp_config` pointed at a news/market data source) into those two agent configs, or pull them out of the swarm and call `/v1/agent/completions` for each with the top-level `"tools_enabled": ["auto_search"]` field, which does enable a live Exa-backed search tool for that endpoint. </Note> ## Step 3: Run the Concurrent Swarm One POST to `/v1/swarm/completions` with `swarm_type: "ConcurrentWorkflow"`. All three agents execute in parallel; you get an `output` array back keyed by `role`. ```python theme={null} def run_briefing_swarm(calendar_today: str) -> dict[str, str]: payload = { "name": "Daily Morning Briefing", "swarm_type": "ConcurrentWorkflow", "task": ( "Produce the morning briefing. News Curator: top 3 stories. " "Market Watcher: pre-market snapshot. Calendar Briefer: reformat " f"this raw calendar: {calendar_today}" ), "agents": AGENTS, "max_loops": 1, } r = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json=payload, timeout=180, ) r.raise_for_status() return {o["role"]: o["content"] for o in r.json().get("output", [])} ``` ## Step 4: Synthesize Into a Slack Block A tiny synthesizer function turns the three agent outputs into a Slack `blocks` payload. No LLM call here — just string assembly. Cheap, fast, deterministic. ```python theme={null} def build_slack_blocks(sections: dict[str, str]) -> dict: today = datetime.now().strftime("%A, %B %d, %Y") header = f":sunrise: *Morning Briefing — {today}*" body = ( f"*:chart_with_upwards_trend: Market Watcher*\n{sections.get('Market Watcher','(no data)')}\n\n" f"*:newspaper: News Curator*\n{sections.get('News Curator','(no data)')}\n\n" f"*:calendar: Calendar Briefer*\n{sections.get('Calendar Briefer','(no data)')}" ) return {"blocks": [ {"type": "section", "text": {"type": "mrkdwn", "text": header}}, {"type": "divider"}, {"type": "section", "text": {"type": "mrkdwn", "text": body}}, ]} ``` ## Step 5: Post to Slack The webhook accepts JSON. One line. ```python theme={null} requests.post(os.environ["SLACK_WEBHOOK_URL"], json=payload, timeout=10).raise_for_status() ``` ## Step 6: Schedule It for 7AM Every Weekday Save the script to `/opt/briefing/brief.py` on any always-on Linux box and add one line to your crontab (`crontab -e`): ``` 0 7 * * 1-5 cd /opt/briefing && /usr/bin/python brief.py >> /var/log/briefing.log 2>&1 ``` That's it. Monday through Friday at 7:00 local time, your channel gets the briefing. <AccordionGroup> <Accordion title="On macOS (no cron) — use launchd"> Create `~/Library/LaunchAgents/com.you.briefing.plist` with a `StartCalendarInterval` block for `Hour=7, Minute=0, Weekday=1..5`, point `ProgramArguments` at `/usr/bin/python3 /Users/you/briefing/brief.py`, then `launchctl load` it. macOS handles wake-on-schedule for you. </Accordion> <Accordion title="On a Linux server — prefer a systemd timer"> Create `briefing.service` (Type=oneshot, ExecStart=python brief.py) and `briefing.timer` (OnCalendar=Mon..Fri 07:00). `systemctl enable --now briefing.timer`. You get logs in `journalctl -u briefing.service`, no cron mail noise, and persistent timer state across reboots. </Accordion> <Accordion title="On a serverless platform — easier still"> Drop the script into a GitHub Actions workflow with `on: schedule: cron: '0 7 * * 1-5'`, or use a Vercel/Modal/Render cron job. No box to maintain. </Accordion> </AccordionGroup> ## The Full Script (\~55 lines) Copy this into `brief.py`, set the two env vars, and you're done. ```python theme={null} import os from datetime import datetime import requests from dotenv import load_dotenv load_dotenv() AGENTS = [ { "agent_name": "News Curator", "system_prompt": ( "You are a morning news curator. Surface the 3 most important stories " "from the last 24 hours relevant to AI, tech, and macro markets. " "Output exactly 3 bullets, each one line, with the source in parentheses. " "No preamble." ), "model_name": "gemini-2.5-pro", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Market Watcher", "system_prompt": ( "You are a pre-market briefer. Report S&P 500 futures, 10Y yield, " "two notable single-stock moves, and BTC/ETH levels. " "Output 3 bullets max, one line each, numbers first. No disclaimers." ), "model_name": "grok-4", "max_loops": 1, "temperature": 0.2, }, { "agent_name": "Calendar Briefer", "system_prompt": ( "You are a calendar briefer. Reformat the user's raw calendar string into " "clean bullets sorted by start time, format 'HH:MM — Title (duration)'. " "One bullet per meeting. No summary line." ), "model_name": "claude-haiku-4.5", "max_loops": 1, "temperature": 0.1, }, ] def run_briefing_swarm(cal: str) -> dict[str, str]: payload = {"name": "Daily Morning Briefing", "swarm_type": "ConcurrentWorkflow", "task": f"Produce the morning briefing. Calendar raw: {cal}", "agents": AGENTS, "max_loops": 1} r = requests.post("https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json=payload, timeout=180) r.raise_for_status() return {o["role"]: o["content"] for o in r.json().get("output", [])} def build_slack_blocks(s: dict[str, str]) -> dict: today = datetime.now().strftime("%A, %B %d, %Y") body = (f"*:chart_with_upwards_trend: Market Watcher*\n{s.get('Market Watcher','(no data)')}\n\n" f"*:newspaper: News Curator*\n{s.get('News Curator','(no data)')}\n\n" f"*:calendar: Calendar Briefer*\n{s.get('Calendar Briefer','(no data)')}") return {"blocks": [ {"type": "section", "text": {"type": "mrkdwn", "text": f":sunrise: *Morning Briefing — {today}*"}}, {"type": "divider"}, {"type": "section", "text": {"type": "mrkdwn", "text": body}}, ]} if __name__ == "__main__": sections = run_briefing_swarm(os.environ.get("CALENDAR_TODAY", "(no meetings today)")) requests.post(os.environ["SLACK_WEBHOOK_URL"], json=build_slack_blocks(sections), timeout=10).raise_for_status() print("Briefing posted.") ``` ## Variations * **Swap News Curator for a Hacker News Curator** — change the system prompt to "Top 3 HN front-page stories from the last 24h with comment counts". * **Add a Weather Briefer** — fourth concurrent agent, prompt: "One-line forecast and high/low for ". * **Post to Discord instead of Slack** — Discord webhooks accept the same JSON shape with `content` instead of `blocks`; swap the synthesizer. * **Send via email** — replace the Slack POST with `smtplib.SMTP` and render the same string as plain text. * **Post at end-of-day with a wrap-up** — flip the cron to `0 17 * * 1-5`, retarget the prompts to "today's closing recap" and "what shipped on HN today". ## Real Cost Three agents, one run per weekday, \~21 runs/month. Each run uses roughly 1,500 input tokens and 600 output tokens across the swarm. At current pricing (\$0.01 per agent, \$6.50/1M input tokens, \$18.50/1M output tokens) that's about **\$0.05 per briefing × 21 runs = \~\$1.05/month**. Around a dollar a month for a deployment your team will notice if it ever fails. Add a live search tool per the note in Step 2 and factor in its per-call cost on top of this. ## Next Steps * [Concurrent Workflow](/docs/examples/examples/concurrent-workflow) — the full pattern for parallel agents and when to reach for it * [Search-Enabled Agents](/docs/examples/examples/search-enabled) — how to wire a live search tool into an agent, including how to inspect the citations * [Batch Processing](/docs/examples/examples/batch-processing) — when one briefing isn't enough and you want a briefing per team, per region, or per portfolio company on one cron tick # DCF Builder + Sensitivity Tables: Per-Name Daily Refresh Source: https://docs.swarms.ai/docs/examples/examples/dcf-builder-sensitivity Reason the assumptions with Opus 4.8 at high effort, build the DCF mechanically through a SequentialWorkflow, and refresh 50 names every night via batch completions for under $80 of overnight compute. ## What This Example Shows * A reasoning agent on `claude-opus-4-8` with `reasoning_effort: "high"` setting the load-bearing inputs: revenue growth, margin trajectory, terminal growth, WACC * A four-stage `SequentialWorkflow` that turns the reasoned assumptions into an audited DCF, sensitivity grids, and an analyst-grade memo * Per-agent function tools that pull income statement, balance sheet, cash flow, consensus estimates, and run the actual DCF math * A 50-name overnight refresh fired as one POST to `/v1/swarm/batch/completions`, scheduled in the night-mode window for a 50% discount * A structured one-pager memo per ticker — exec summary, fair value bands, sensitivity tables, key assumptions, risks — sitting in the database before 6am Pacific <Info> `/v1/agent/batch/completions` and `/v1/swarm/batch/completions` are Premium-tier features. Pair them with the [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) — overnight execution between 8pm and 6am Pacific is billed at a 50% discount, which is what makes a 50-name nightly DCF refresh land under \$80 of compute. </Info> ## Why This Matters The DCF is the load-bearing instrument of fundamental investing. Every BUY thesis at a long-only fund eventually reduces to a sheet that says "I think this company's free cash flow ramps from X to Y, discounted at Z, gives me a fair value of W per share." Refreshing one DCF properly — pulling the latest statements, re-reasoning the assumptions against the most recent quarter, rerunning sensitivities, and writing the memo — is half a day of associate work. A 50-name portfolio refresh through earnings season is a team of associates working for weeks. The job here is to do that work overnight, mechanically, with the reasoning step handled by Opus at high effort so the assumptions are actually defensible — and the math handled by cheaper mechanical models because the math is just math. Every morning at 6am Pacific, fifty fresh DCFs are sitting in the DB — assumptions reasoned by Opus, math run mechanically, memos written like an associate did them, for under \$80 of overnight compute. ## The Architecture One reasoning pass per ticker sets the assumptions. A four-stage Sequential pipeline turns those assumptions into a model, runs the sensitivity tables, and writes the memo. The whole thing fans out 50-wide as a single batch POST. ```text theme={null} +----------------+ | Ticker | +--------+-------+ | v +----------------------+ | Fetch Financials | fetch_income_statement, fetch_balance_sheet, | (function tools) | fetch_cash_flow, fetch_consensus_estimates +--------+-------------+ | v +----------------------+ | Reasoning | claude-opus-4-8 | Hypothesis Agent | reasoning_effort: "high" | (sets assumptions) | -> revenue growth, margin path, +--------+-------------+ terminal growth, WACC | v +-----------------------------------------------------+ | SequentialWorkflow | | | | +------------------+ +------------------------+ | | | Assumptions |-->| DCF Model | | | | Builder (gpt-4.1)| | (gpt-4.1-mini) | | | +------------------+ +-----------+------------+ | | | | | v | | +------------------+ +------------------------+ | | | Memo Writer |<--| Sensitivity Tables | | | | (claude-sonnet- | | (gpt-4.1-mini) | | | | 4.5) | +------------------------+ | | +--------+---------+ | +-----------|------------------------------------------+ | v +----------------------+ | Markdown One-Pager | exec summary, fair value bands, +--------+-------------+ sensitivity tables, risks | v +----------------------+ | Database | 50 memos by 6am Pacific +----------------------+ ``` ## Step 1: Setup Install dependencies and set the two env vars. `FMP_API_KEY` is Financial Modeling Prep — any equivalent statements provider works; the function-tool schemas below are the contract, not the vendor. ```bash theme={null} pip install requests python-dotenv ``` ```bash theme={null} export SWARMS_API_KEY="your-swarms-key" export FMP_API_KEY="your-fmp-key" ``` ```python theme={null} import json import os from datetime import datetime import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") FMP_KEY = os.getenv("FMP_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools These are OpenAI-format function schemas the agents call to pull data and run mechanical math. Define them once; attach via `tools_list_dictionary` to whichever agent needs them. ```python theme={null} FETCH_INCOME_STATEMENT = { "type": "function", "function": { "name": "fetch_income_statement", "description": ( "Pull the most recent N years of annual income statements for a " "ticker. Returns revenue, gross profit, operating income, net " "income, EPS, and shares outstanding per year." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string", "description": "Equity ticker symbol."}, "years": {"type": "integer", "description": "Years of history.", "default": 5}, }, "required": ["ticker"], }, }, } FETCH_BALANCE_SHEET = { "type": "function", "function": { "name": "fetch_balance_sheet", "description": ( "Pull the most recent N years of annual balance sheets. Returns " "cash, total debt, equity, working capital line items." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string"}, "years": {"type": "integer", "default": 5}, }, "required": ["ticker"], }, }, } FETCH_CASH_FLOW = { "type": "function", "function": { "name": "fetch_cash_flow", "description": ( "Pull the most recent N years of annual cash flow statements. " "Returns operating CF, capex, free cash flow, SBC, working " "capital movement." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string"}, "years": {"type": "integer", "default": 5}, }, "required": ["ticker"], }, }, } FETCH_CONSENSUS_ESTIMATES = { "type": "function", "function": { "name": "fetch_consensus_estimates", "description": ( "Pull sell-side consensus estimates for revenue, EBIT, EPS, and " "FCF for the next 3 fiscal years." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string"}, }, "required": ["ticker"], }, }, } CALC_WACC = { "type": "function", "function": { "name": "calc_wacc", "description": ( "Calculate weighted average cost of capital for the ticker. " "Uses CAPM for cost of equity (rfr + beta * ERP), after-tax cost " "of debt from the company's interest expense, and the current " "capital structure weights." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string"}, "beta": {"type": "number", "description": "Levered equity beta."}, "rfr": {"type": "number", "description": "Risk-free rate.", "default": 0.045}, }, "required": ["ticker", "beta"], }, }, } BUILD_DCF = { "type": "function", "function": { "name": "build_dcf", "description": ( "Run a 10-year explicit-forecast DCF given a structured assumptions " "object. Returns per-year FCF, terminal value, enterprise value, " "equity value, fair value per share, and the implied upside vs. " "spot." ), "parameters": { "type": "object", "properties": { "assumptions_json": { "type": "object", "description": ( "Structured assumptions: ticker, base_revenue, " "revenue_growth (array of 10 floats), " "ebit_margin (array of 10 floats), tax_rate, " "capex_pct_revenue, working_capital_pct_revenue, " "wacc, terminal_growth, net_debt, shares_outstanding." ), }, }, "required": ["assumptions_json"], }, }, } SENSITIVITY_TABLE = { "type": "function", "function": { "name": "sensitivity_table", "description": ( "Build a 2-D sensitivity grid on the DCF, varying two named " "assumption keys across the given range. Returns a matrix of " "fair value per share at each cell." ), "parameters": { "type": "object", "properties": { "model_json": { "type": "object", "description": "The output of build_dcf — the baseline model.", }, "var1": { "type": "string", "description": "First assumption key, e.g. 'wacc'.", }, "var2": { "type": "string", "description": "Second assumption key, e.g. 'terminal_growth'.", }, "range": { "type": "object", "description": ( "Symmetric range for each variable as {var1: [low, " "high, steps], var2: [low, high, steps]}." ), }, }, "required": ["model_json", "var1", "var2", "range"], }, }, } ALL_DATA_TOOLS = [ FETCH_INCOME_STATEMENT, FETCH_BALANCE_SHEET, FETCH_CASH_FLOW, FETCH_CONSENSUS_ESTIMATES, CALC_WACC, ] MODEL_TOOLS = [BUILD_DCF, SENSITIVITY_TABLE] ``` <Note> The tool schemas are the contract — your backend resolves them against whatever data vendor you use. For a self-contained walkthrough, the Reasoning agent and the DCF Model worker can both make the function calls; the orchestrator delivers the resolved tool outputs back into the conversation. The math tools (`build_dcf`, `sensitivity_table`) are mechanical — wire them to a pure-Python DCF library, not an LLM. </Note> ## Step 3: The Reasoning Assumption Agent This is the only step where you spend real model dollars. Opus 4.8 at `reasoning_effort: "high"` reads the last five years of financials, the consensus, and the company's own guidance, and produces a defensible set of assumptions — not a wishlist. Everything downstream is mechanical. ```python theme={null} ASSUMPTION_REASONER_PROMPT = ( "You are a senior buy-side analyst building the assumptions for a 10-year " "DCF. You will receive the last 5 years of income statement, balance " "sheet, and cash flow, plus consensus estimates and the company's own " "guidance.\n\n" "Your job is to set, with reasoning, every load-bearing input:\n" "1. Revenue growth — 10 years, declining toward GDP\n" "2. EBIT margin — 10 years, normalized to a steady-state\n" "3. Tax rate — effective, not statutory\n" "4. Capex as % of revenue — through-cycle\n" "5. Working capital intensity\n" "6. WACC — derive via calc_wacc tool\n" "7. Terminal growth — 2.0%-2.5% unless you defend otherwise\n\n" "For each input write one sentence of justification grounded in the " "pulled data. Do NOT eyeball. If you assume revenue grows 15% in year " "3, name the driver. If your terminal growth is above 2.5%, defend it " "against GDP.\n\n" "Output a single JSON object: ticker, base_revenue, revenue_growth (10 " "floats), ebit_margin (10 floats), tax_rate, capex_pct_revenue, " "working_capital_pct_revenue, wacc, terminal_growth, net_debt, " "shares_outstanding, plus an 'assumption_notes' object keyed by each " "field name with a one-sentence justification." ) def reasoning_assumptions_agent_config(ticker: str) -> dict: return { "agent_name": "Assumption Reasoner", "description": ( "Sets the load-bearing DCF assumptions with high-effort reasoning." ), "system_prompt": ASSUMPTION_REASONER_PROMPT, "model_name": "claude-opus-4-8", "reasoning_effort": "high", "role": "worker", "max_loops": 1, "max_tokens": 8000, "temperature": 0.2, "tools_list_dictionary": ALL_DATA_TOOLS, } ``` <Note> `reasoning_effort: "high"` is what makes the assumptions defensible. On medium effort, the agent will frequently anchor on consensus without questioning the path; on high effort, it interrogates margin trajectory and capex against actual historical patterns. This is the one place to spend. </Note> ## Step 4: The SequentialWorkflow Pipeline Four workers, each cheap, each doing one well-defined job. The Assumptions Builder ingests the reasoned output and emits a strict JSON spec the math layer can consume. The DCF Model and Sensitivity Tables are mechanical — they call `build_dcf` and `sensitivity_table` and report results. The Memo Writer is the only stage that needs prose quality, and Sonnet handles that cheaply. ```python theme={null} def build_dcf_swarm(ticker: str, reasoning_output: str) -> dict: return { "name": f"DCF Pipeline — {ticker}", "description": ( f"Per-ticker DCF builder for {ticker} — assumptions reasoned by " "Opus, math run mechanically, memo written analyst-grade." ), "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": ( f"Build a one-page DCF memo on {ticker}. The reasoned assumption " f"set from the upstream Opus pass is:\n\n{reasoning_output}\n\n" "Carry this forward through the pipeline." ), "agents": [ { "agent_name": "Assumptions Builder", "description": ( "Digests the reasoning output into a strict JSON spec " "for the mechanical model." ), "system_prompt": ( "You are a model engineer. Take the upstream reasoning " "and produce a single JSON object matching the build_dcf " "schema EXACTLY: ticker, base_revenue, revenue_growth (10 " "floats), ebit_margin (10 floats), tax_rate, " "capex_pct_revenue, working_capital_pct_revenue, wacc, " "terminal_growth, net_debt, shares_outstanding. Do not " "alter the reasoned numbers. Drop the prose. Output ONLY " "the JSON spec." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2000, "temperature": 0.0, }, { "agent_name": "DCF Model", "description": "Runs the mechanical 10-year DCF.", "system_prompt": ( "You are a quant. Call build_dcf with the upstream JSON " "spec. Return the full model output: per-year FCF, " "discounted FCF, terminal value, enterprise value, equity " "value, fair value per share, and implied upside vs. spot. " "Do not editorialize. Pass through the numbers." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 3000, "temperature": 0.0, "tools_list_dictionary": MODEL_TOOLS, }, { "agent_name": "Sensitivity Tables", "description": "Runs 3 standard 2-D sensitivity grids.", "system_prompt": ( "You are a quant. Using the upstream baseline model, call " "sensitivity_table three times:\n" "1. WACC (±150 bps, 7 steps) × Terminal Growth (1.0%-3.5%, " "6 steps)\n" "2. EBIT Margin Year-10 (±300 bps, 7 steps) × Revenue " "Growth Y1-3 CAGR (±5pts, 6 steps)\n" "3. Capex % Revenue (±200 bps, 5 steps) × Terminal " "Growth (1.0%-3.5%, 6 steps)\n" "Return each grid as a labeled markdown table." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 4000, "temperature": 0.0, "tools_list_dictionary": MODEL_TOOLS, }, { "agent_name": "Memo Writer", "description": "Writes the analyst-grade one-pager memo.", "system_prompt": ( "You are a senior buy-side associate writing a one-page " "DCF memo for the PM. Use the upstream assumption notes, " "the DCF model output, and the three sensitivity tables. " "Structure the memo EXACTLY as:\n\n" "# {TICKER} — DCF Refresh ({date})\n\n" "## Executive Summary\n" "(3 lines: fair value, upside vs. spot, conviction)\n\n" "## Target Price & Fair-Value Bands\n" "Base / Bull / Bear with the assumption shifts.\n\n" "## Key Assumptions\n" "Table: assumption, value, justification (one line each).\n\n" "## Sensitivity Tables\n" "All three grids with one-line readers' guides.\n\n" "## Risks to the Thesis\n" "Top 3, ranked.\n\n" "## Recommendation\n" "ADD / HOLD / TRIM with a one-sentence justification.\n\n" "Keep total length under 800 words." ), "model_name": "claude-sonnet-4.5", "role": "worker", "max_loops": 1, "max_tokens": 4000, "temperature": 0.3, }, ], } ``` ## Step 5: Run One Ticker End-to-End Run the reasoning pass first, hand its output to the Sequential pipeline, print the memo. This is the loop you will scale. ```python theme={null} def run_assumption_reasoner(ticker: str) -> str: payload = { "agent_config": reasoning_assumptions_agent_config(ticker), "task": ( f"Pull the last 5 years of statements and consensus for {ticker}. " "Set every DCF input with one-sentence reasoning per input. Output " "the structured JSON spec described in your system prompt." ), } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=600, ) response.raise_for_status() result = response.json() text = "" for entry in result.get("outputs", []): content = entry.get("content", "") if isinstance(content, list): content = " ".join(str(c) for c in content) text = str(content) return text def run_dcf_pipeline(ticker: str) -> dict: reasoning_output = run_assumption_reasoner(ticker) payload = build_dcf_swarm(ticker, reasoning_output) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=900, ) response.raise_for_status() return response.json() result = run_dcf_pipeline("NVDA") memo = "" for output in result.get("output", []): if "Memo Writer" in output.get("role", ""): content = output.get("content", "") if isinstance(content, list): content = " ".join(str(c) for c in content) memo = str(content) print(memo) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` ## Step 6: Overnight Portfolio Refresh The whole point. Fan the same per-ticker pipeline across 50 names as a single batch POST. Schedule the cron at 9pm Pacific so the entire batch runs inside the night-mode window and bills at 50% off. ```python theme={null} PORTFOLIO = [ "NVDA", "AAPL", "MSFT", "GOOGL", "META", "AMZN", "TSLA", "AMD", "AVGO", "CRM", "ORCL", "ADBE", "NFLX", "INTU", "TXN", "QCOM", "ASML", "LRCX", "AMAT", "KLAC", "ANET", "PANW", "CRWD", "ZS", "NET", "MDB", "TEAM", "WDAY", "NOW", "SNOW", "DDOG", "ABNB", "DASH", "SPOT", "TTD", "APP", "UBER", "PLTR", "COIN", "SHOP", "JPM", "BAC", "GS", "MS", "WFC", "BLK", "SCHW", "V", "MA", "BRK.B", ] def run_portfolio_refresh(tickers: list[str]) -> list[dict]: # Step 1: Reason assumptions for every ticker via the batch agent # endpoint. The endpoint caps each request at 50 agent completions, # so chunk the portfolio; results come back in input order under # the response's "results" key. reasoned_assumptions = [] for i in range(0, len(tickers), 10): reasoning_payload = [ { "agent_config": reasoning_assumptions_agent_config(t), "task": ( f"Pull the last 5 years of statements and consensus for {t}. " "Set every DCF input with one-sentence reasoning. Output the " "structured JSON spec." ), } for t in tickers[i : i + 10] ] reasoning_resp = requests.post( f"{BASE_URL}/v1/agent/batch/completions", headers=headers, json=reasoning_payload, timeout=3600, ) reasoning_resp.raise_for_status() for r in reasoning_resp.json().get("results", []): text = "" for entry in r.get("outputs", []): content = entry.get("content", "") if isinstance(content, list): content = " ".join(str(c) for c in content) text = str(content) reasoned_assumptions.append(text) # Step 2: Fan out 50 SequentialWorkflows as a single batch swarm_payload = [ build_dcf_swarm(t, reasoned) for t, reasoned in zip(tickers, reasoned_assumptions) ] swarm_resp = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=swarm_payload, timeout=3600, ) swarm_resp.raise_for_status() return swarm_resp.json() def persist_memos(tickers: list[str], results: list[dict]) -> None: # Each batch item is {"status", "swarm_name", "result", "usage"} and # items come back in input order — the swarm name is still the safest # way to recover the ticker. date = datetime.utcnow().strftime("%Y-%m-%d") by_name = {r.get("swarm_name", ""): r for r in results} with open(f"dcf_memos_{date}.jsonl", "w") as f: for ticker in tickers: r = by_name.get(f"DCF Pipeline — {ticker}", {}) memo = "" for output in r.get("result", []) or []: if "Memo Writer" in output.get("role", ""): content = output.get("content", "") if isinstance(content, list): content = " ".join(str(c) for c in content) memo = str(content) f.write(json.dumps({"ticker": ticker, "date": date, "memo": memo}) + "\n") results = run_portfolio_refresh(PORTFOLIO) persist_memos(PORTFOLIO, results) total_cost = sum(r.get("usage", {}).get("billing_info", {}).get("total_cost", 0) for r in results) print(f"Refreshed {len(results)} DCFs for ${total_cost:.2f}") ``` The cron line that fires the refresh inside the night-mode window: ```bash theme={null} # Nightly DCF refresh — 9:00 PM Pacific, weekdays 0 21 * * 1-5 cd /opt/dcf && /usr/bin/python overnight_refresh.py >> /var/log/dcf_refresh.log 2>&1 ``` <Info> The batch lands in the database by \~5am Pacific. See [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) for why scheduling between 8pm and 6am Pacific cuts the bill in half — the same workload at 11am Pacific is twice as expensive for identical output. </Info> ## Step 7: The Memo Output Format Every memo lands in the database with the same skeleton. The PM reads the executive summary on every name in five minutes; they drill into the sensitivity tables only on names where the call is close. ```markdown theme={null} # NVDA — DCF Refresh (2026-05-28) ## Executive Summary Fair value per share: $148 (base). Implied upside vs. $112 spot: +32%. Conviction: HIGH — assumption set survives ±150bps WACC stress. ## Target Price & Fair-Value Bands | Scenario | Fair Value | Upside | Key Shift | |----------|-----------|--------|-----------| | Bull | $182 | +63% | EBIT margin holds 38% in Y10 | | Base | $148 | +32% | Margin normalizes to 34% by Y10 | | Bear | $96 | -14% | Capex steps up 200bps + WACC 11% | ## Key Assumptions | Assumption | Value | Justification | |------------|-------|---------------| | Revenue growth Y1-3 CAGR | 38% | Data center backlog through FY27 | | Revenue growth Y4-10 | declines 28% -> 6% | Reverts toward semis steady-state | | EBIT margin Y10 | 34% | Above-cycle vs. historical 28% — defend on AI mix | | Terminal growth | 2.5% | Above GDP defensible on AI infrastructure decade | | WACC | 9.2% | Beta 1.45, ERP 5.0%, rfr 4.5%, cost of debt 4.8% | | Capex % revenue | 8.5% | Elevated vs. 6.5% trailing — fabs and platform | ## Sensitivity Tables ### WACC × Terminal Growth (fair value per share) | | TG 1.0% | 1.5% | 2.0% | 2.5% | 3.0% | 3.5% | |---|---|---|---|---|---|---| | **WACC 8.0%** | $158 | $172 | $189 | $211 | $241 | $283 | | **WACC 8.7%** | $138 | $148 | $161 | $176 | $196 | $223 | | **WACC 9.2%** | $126 | $135 | $145 | $158 | $173 | $193 | | **WACC 10.0%** | $110 | $116 | $124 | $133 | $144 | $158 | Read: at base WACC 9.2%, the model breaks $130 even at 1.0% terminal growth. ### EBIT Margin Y10 × Revenue Growth Y1-3 CAGR (Same grid format, 7×6.) ### Capex % Revenue × Terminal Growth (Same grid format, 5×6.) ## Risks to the Thesis 1. Hyperscaler capex pause through 2H26 cuts Y1-2 growth 1500-2000bps. 2. China export control tightening removes 12-15% of incremental TAM. 3. Custom silicon at top-3 customers compresses pricing in Y3+. ## Recommendation ADD — base case fair value clears spot by 32% and the sensitivity grid shows the call survives reasonable assumption stress. ``` ## Real Cost vs. IB Associate Time The hero number — and it isn't subtle. | Approach | Per-ticker cost | Nightly (50 names) | Annualized | Refresh latency | | ----------------------------------------------------------------- | --------------- | ---------------------- | -------------- | -------------------------- | | **This pipeline (Opus reasoning + Sequential math + night-mode)** | **\~\$1.50** | **\~\$75** | **\~\$19,000** | **Overnight, every name** | | One IB associate, fully loaded \$250k | — | \~\$1,000 of their day | \~\$250,000 | 5 names/day before burnout | | Three-associate coverage pod | — | \~\$3,000 of their day | \~\$750,000 | 12-15 names/day | A single associate covers maybe five names a day before quality degrades. Three associates cover fifteen. The portfolio has fifty. The math has never worked — every fundamental shop either ships stale DCFs or ships none. This pipeline ships fifty fresh DCFs every morning before the desk arrives, for **less than 8% of one associate's salary** and roughly **3% of the three-associate pod's cost**. The associate isn't replaced — they spend their day on the names the memo flagged as conviction-changing, instead of grinding through statement updates that didn't move the call. <Warning> DCF memos generated by this pipeline are research artifacts. The assumption\_notes from the Opus reasoning pass are the audit trail; the sensitivity tables are the stress test. Before any output reaches an IC vote or an LP, the memo passes through a signoff queue where a human reviews the assumption justifications and signs off on the recommendation. The pipeline doesn't carry investment authority. </Warning> ## Next Steps * [Build an AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) — the HierarchicalSwarm pattern for buy/sell/hold calls upstream of the DCF refresh * [Reasoning Agents for Hard Analytical Problems](/docs/examples/examples/reasoning-agents-tutorial) — the standalone primitive for the Opus reasoning pass, with the full `swarm_type` catalog * [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) — why scheduling the batch between 8pm and 6am Pacific is what makes the 50-name refresh land under \$80 # Debate With Judge Example Source: https://docs.swarms.ai/docs/examples/examples/debate-with-judge Build a structured debate with progressive refinement using DebateWithJudge ## Technology Strategy Debate This example demonstrates how to set up a structured debate between opposing agents with an impartial judge using DebateWithJudge — ideal for decision-making, policy analysis, and evaluating trade-offs on complex topics. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define the Debate Panel Create exactly 3 agents — a Pro debater, a Con debater, and a Judge — who will engage in structured argumentation: ```python theme={null} def run_debate(topic: str, max_loops: int = 1) -> dict: """Run a structured debate with judge evaluation.""" swarm_config = { "name": "Tech Strategy Debate", "description": "Structured debate with progressive refinement", "swarm_type": "DebateWithJudge", "task": topic, "agents": [ { "agent_name": "Pro Debater", "description": "Argues in favor of the proposition", "system_prompt": "You are an expert debater arguing IN FAVOR of the given proposition. Present well-structured arguments with evidence, data, and concrete examples. Anticipate counterarguments and address them. In refinement rounds, strengthen your case based on the judge's feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Con Debater", "description": "Argues against the proposition", "system_prompt": "You are an expert debater arguing AGAINST the given proposition. Identify weaknesses, risks, and unintended consequences. Challenge assumptions with data and real-world counterexamples. In refinement rounds, sharpen your opposition based on the judge's feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Debate Judge", "description": "Evaluates arguments and provides synthesis", "system_prompt": "You are an impartial judge evaluating a structured debate. Assess both sides on logical coherence, evidence quality, and persuasiveness. Identify the strongest points from each side. Provide a clear verdict with justification, synthesizing the best elements from both arguments into a balanced conclusion.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": max_loops } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 3: Run the Debate ```python theme={null} # Define the debate topic topic = """ Should startups build their initial product on a microservices architecture or a monolithic architecture? Consider development speed, scalability, operational complexity, team size constraints, and long-term maintainability. """ # Run the debate result = run_debate(topic) # Display the debate for output in result.get("output", []): role = output["role"] content = output["content"] print(f"\n{'='*60}") print(f"{role}") print(f"{'='*60}") if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:800] + "...") ``` **Expected Output:** ``` ============================================================ Pro Debater ============================================================ Startups should absolutely begin with a monolithic architecture. Here's the evidence-based case: 1. DEVELOPMENT SPEED: A monolith eliminates inter-service communication overhead. Shopify scaled to $5.6B revenue on a Ruby on Rails monolith. Instagram had 30M users on a Django monolith before acquisition. 2. TEAM SIZE: Startups typically have 2-8 engineers. Microservices require dedicated DevOps — a luxury most early-stage teams cannot afford. The overhead of managing service discovery, API contracts, and distributed debugging slows a small team... ============================================================ Con Debater ============================================================ The monolith-first argument ignores critical modern realities: 1. CLOUD-NATIVE TOOLING: In 2024, frameworks like Next.js API routes, AWS Lambda, and Vercel serverless functions make microservices nearly as easy to deploy as monoliths. The operational overhead argument is outdated. 2. SCALING BOTTLENECKS: Monoliths force you to scale everything together. If your search feature needs 10x the compute of your auth service, you're paying for 10x across the board... ============================================================ Debate Judge ============================================================ Both sides present compelling arguments. Here is my evaluation: PRO STRENGTHS: The development speed argument is well-supported by real examples (Shopify, Instagram). The team size constraint is a practical reality for most early-stage startups. CON STRENGTHS: The point about modern cloud tooling reducing microservices overhead is valid. The scaling cost argument has merit for compute-intensive applications. VERDICT: For most startups, begin with a modular monolith... ``` ### Step 4: Multi-Loop Refinement Run multiple debate rounds where the judge's feedback helps both sides sharpen their arguments: ```python theme={null} # Run 2 loops — debaters refine their arguments based on judge feedback deep_result = run_debate( topic="Should AI companies open-source their foundation models? Consider innovation speed, safety risks, competitive moats, and societal benefit.", max_loops=2 ) # Show the final contributions after 2 rounds of refinement for output in deep_result.get("output", []): print(f"\n{output['role']}:") content = output["content"] if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:600] + "...") ``` <Note> DebateWithJudge requires exactly 3 agents in order: Pro (argues in favor), Con (argues against), and Judge (evaluates and synthesizes). Increasing `max_loops` enables progressive refinement — each round produces stronger arguments as debaters respond to the judge's feedback from the previous round. </Note> # Earnings Call Analysis Swarm: Tone, Guidance, and Q&A Red Flags in 60 Seconds Source: https://docs.swarms.ai/docs/examples/examples/earnings-call-analysis-swarm A ConcurrentWorkflow of four specialist agents plus a Synthesizer turns every earnings call transcript into a structured note — covering all 125 calls per day during peak earnings season for under $50. ## What This Example Shows * A `ConcurrentWorkflow` of four specialists — Transcript Analyzer, Guidance Tracker, Q\&A Sentiment, Material Disclosure Detector — fanning out in parallel, then merged by a Synthesizer agent * Per-agent function tools in OpenAI schema (`tools_list_dictionary`): `score_tone`, `compare_guidance`, `detect_material_disclosure`, `extract_qa_red_flags` * Mixed-provider model routing: Claude Sonnet 4.5 for analysis and synthesis, GPT-4.1 for guidance arithmetic, Claude Haiku 4.5 for cheap sentiment, Claude Opus 4.8 with `reasoning_effort: "high"` for the high-stakes disclosure check * How to scale a single call across the full earnings-season firehose using `/v1/swarm/batch/completions` * A cron pattern that fires at 5pm ET each day so the desk wakes up to a structured note on every transcript filed the day before * Real per-call and per-day economics against a sell-side analyst at peak burn <Info> Batch completions and observability dashboards are Premium-tier features. During the 3-week earnings burst a sell-side desk will push 500+ calls through this pipeline — that's exactly the workload Premium rate limits, parallel batch execution, and per-agent token tracing exist for. See the [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) guide for why running the batch off-peak (after the 4pm ET tape) is the right default for any scheduled earnings workload. </Info> ## Why This Matters A sell-side analyst on a 14-hour day during peak earnings season can read, parse, model, and write up maybe six to eight earnings calls before they fall over. A US large-cap sector publishes 125 prints on a single Thursday in late January or late April. The math has never worked. Every call after the eighth is either (a) skimmed from the press release and a Bloomberg headline, (b) covered the next morning when the tape has already moved, or (c) skipped entirely. The job of this pipeline is not to replace the analyst's read — it is to put a structured note on every call before the analyst sits down: tone score, guidance delta vs. last quarter, Q\&A red flags, and a flag for anything that looks like a material disclosure. The human then spends their finite hours on the names that actually need their judgment. **By 4:45pm ET your DB has a structured note on every call — tone, guidance delta, red-flag Q\&A — for under \$50 a day.** ## The Architecture Four specialists run in parallel against the same transcript. A Synthesizer agent merges their outputs into one structured note, which gets persisted to the research DB and pinged to Slack. ```text theme={null} +----------------------------+ | Earnings Call Transcript | | (from filing/feed/upload) | +-------------+--------------+ | v +----------------------------+ ConcurrentWorkflow — all four fire in parallel | ConcurrentWorkflow | | | | +----------------------+ | | | Transcript Analyzer | | -> score_tone() | | (claude-sonnet-4-5) | | | +----------------------+ | | | | +----------------------+ | | | Guidance Tracker | | -> compare_guidance(this_qtr, prior_qtr) | | (gpt-4.1) | | | +----------------------+ | | | | +----------------------+ | | | Q&A Sentiment | | -> extract_qa_red_flags(qa_section) | | (claude-haiku-4-5) | | | +----------------------+ | | | | +----------------------+ | | | Material Disclosure | | -> detect_material_disclosure() | | (claude-opus-4-8, | | reasoning_effort=high | | reasoning_effort) | | | +----------------------+ | +-------------+--------------+ | v +----------------------------+ | Synthesizer | Merges into a single structured note | (claude-sonnet-4-5) | +-------------+--------------+ | v +----------------------------+ | Structured Note (JSON) | ---> Research DB (Postgres / Snowflake) | | ---> Slack #earnings-firehose +----------------------------+ ``` ## Step 1: Setup Install dependencies and set your API key. The Slack webhook is whatever you've wired into `#earnings-firehose`. ```bash theme={null} pip install requests python-dotenv ``` ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T000/B000/XXXX" ``` ```python theme={null} import json import os from datetime import datetime from pathlib import Path import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") SLACK_URL = os.getenv("SLACK_WEBHOOK_URL") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Each specialist gets one tool, scoped per-agent in OpenAI function schema. The tools force structured output: tone scores, guidance deltas, disclosure verdicts, and Q\&A red flags all come back as parseable JSON the synthesizer (and your DB schema) can rely on. ```python theme={null} SCORE_TONE_TOOL = { "type": "function", "function": { "name": "score_tone", "description": ( "Score the tone of an earnings call transcript across multiple " "dimensions. Returns numeric scores plus a one-line rationale." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "Full transcript or prepared-remarks section.", }, "confidence_score": { "type": "number", "description": ( "Management confidence on a -1.0 (defensive) to " "+1.0 (assertive) scale." ), }, "hedging_score": { "type": "number", "description": ( "Density of hedging language on a 0.0 (none) to " "1.0 (saturated) scale." ), }, "forward_optimism": { "type": "number", "description": ( "Forward-looking optimism on a -1.0 (cautious) to " "+1.0 (bullish) scale." ), }, "rationale": { "type": "string", "description": "One sentence justifying the scores.", }, }, "required": [ "text", "confidence_score", "hedging_score", "forward_optimism", "rationale", ], }, }, } COMPARE_GUIDANCE_TOOL = { "type": "function", "function": { "name": "compare_guidance", "description": ( "Extract forward guidance from this quarter and the prior " "quarter's call and compute the delta on revenue, margin, and " "EPS bands." ), "parameters": { "type": "object", "properties": { "this_qtr_text": { "type": "string", "description": "Guidance section from the current call.", }, "prior_qtr_text": { "type": "string", "description": "Guidance section from the prior quarter's call.", }, "revenue_delta_pct": { "type": "number", "description": ( "Midpoint-to-midpoint revenue guide change as a " "percentage. Negative means a guide-down." ), }, "margin_delta_bps": { "type": "number", "description": ( "Operating margin guide change in basis points. " "Negative means a guide-down." ), }, "eps_delta_pct": { "type": "number", "description": "Midpoint-to-midpoint EPS guide change as a percentage.", }, "guidance_direction": { "type": "string", "enum": ["RAISE", "MAINTAIN", "LOWER", "WITHDRAWN"], "description": "Net direction of the guide.", }, }, "required": [ "this_qtr_text", "prior_qtr_text", "revenue_delta_pct", "margin_delta_bps", "eps_delta_pct", "guidance_direction", ], }, }, } DETECT_MATERIAL_DISCLOSURE_TOOL = { "type": "function", "function": { "name": "detect_material_disclosure", "description": ( "Detect statements on the call that constitute a material " "disclosure under Reg FD — anything previously non-public that " "a reasonable investor would consider important." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "Full transcript.", }, "disclosures": { "type": "array", "description": "List of detected material disclosures.", "items": { "type": "object", "properties": { "quote": { "type": "string", "description": "Verbatim quote from the transcript.", }, "category": { "type": "string", "enum": [ "GUIDANCE_CHANGE", "STRATEGIC_PIVOT", "CUSTOMER_LOSS", "REGULATORY", "LITIGATION", "MA_ACTIVITY", "EXECUTIVE_DEPARTURE", "OTHER", ], }, "materiality": { "type": "string", "enum": ["HIGH", "MEDIUM", "LOW"], }, "rationale": { "type": "string", "description": "Why this is material.", }, }, "required": ["quote", "category", "materiality", "rationale"], }, }, }, "required": ["text", "disclosures"], }, }, } EXTRACT_QA_RED_FLAGS_TOOL = { "type": "function", "function": { "name": "extract_qa_red_flags", "description": ( "Scan the Q&A section of an earnings call for analyst questions " "that management deflected, dodged, or answered with unusual " "hedging. These are the most reliable short-term sentiment " "signals on the entire call." ), "parameters": { "type": "object", "properties": { "qa_section": { "type": "string", "description": "Q&A portion of the transcript.", }, "red_flags": { "type": "array", "description": "List of flagged exchanges.", "items": { "type": "object", "properties": { "analyst": { "type": "string", "description": "Analyst and firm if identifiable.", }, "question_topic": { "type": "string", "description": "What the analyst was probing.", }, "management_response": { "type": "string", "description": "Short summary of the response.", }, "flag_type": { "type": "string", "enum": [ "DEFLECTION", "REFUSED_TO_ANSWER", "EXCESSIVE_HEDGING", "CONTRADICTED_PRIOR_CALL", "OFFLINE_FOLLOWUP", ], }, "severity": { "type": "string", "enum": ["HIGH", "MEDIUM", "LOW"], }, }, "required": [ "analyst", "question_topic", "management_response", "flag_type", "severity", ], }, }, }, "required": ["qa_section", "red_flags"], }, }, } ``` ## Step 3: Define the Five Agents Four specialists run in parallel, each on the model that gives the best cost/quality tradeoff for the job. The Material Disclosure Detector is the only one that gets Claude Opus 4.8 with `reasoning_effort: "high"` — that's the agent whose mistakes are most expensive (a missed Reg FD disclosure on a name your fund holds is a compliance event). The Synthesizer runs Claude Sonnet 4.5 because it has to merge four structured outputs into a clean note without inventing anything. ```python theme={null} TRANSCRIPT_ANALYZER_PROMPT = ( "You are a Sell-Side Earnings Analyst. Read the prepared-remarks section " "of the call and call the `score_tone` tool exactly once. Score management's " "confidence, hedging density, and forward optimism. Be calibrated — a CEO " "reading scripted bullet points should score near 0 on confidence, not +1. " "After the tool call, write a single paragraph (max 80 words) summarizing " "the tonal posture of the call." ) GUIDANCE_TRACKER_PROMPT = ( "You are a Forward Guidance Specialist. Find the guidance section of the " "current call and the prior quarter's guidance section (provided in the " "task). Call `compare_guidance` once. Be precise — use midpoint-to-midpoint " "math, not best-case-to-best-case. If guidance was withdrawn or refused, " "report that explicitly. After the tool call, write a one-sentence " "interpretation of the delta." ) QA_SENTIMENT_PROMPT = ( "You are a Buy-Side Q&A Reader. Read the Q&A section of the call. Call " "`extract_qa_red_flags` once and flag every exchange where management " "deflected, refused, hedged excessively, or pushed the analyst to a " "follow-up offline. Do not flag normal back-and-forth. The signal is " "asymmetric — false negatives matter more than false positives. After " "the tool call, summarize the three most important flags in one paragraph." ) MATERIAL_DISCLOSURE_PROMPT = ( "You are a Securities Compliance Analyst with a Reg FD specialty. Read " "the entire transcript and call `detect_material_disclosure` once. A " "material disclosure is any non-public statement a reasonable investor " "would consider important to a buy/sell decision. Be conservative on " "category labels but inclusive on detection — a missed material event " "is a compliance failure, an over-flagged routine commentary is just " "noise the analyst will skip. After the tool call, write a one-paragraph " "executive summary suitable for a compliance review queue." ) SYNTHESIZER_PROMPT = ( "You are a Research Editor. Four specialists have each analyzed an " "earnings call from a different angle: tone, guidance, Q&A red flags, " "and material disclosures. Merge their outputs into a single structured " "note as STRICT JSON, no Markdown fences. The schema is:\n\n" "{\n" ' "ticker": "<symbol>",\n' ' "period": "<e.g. Q3 2026>",\n' ' "headline": "<one sentence — the dominant takeaway>",\n' ' "tone": {"confidence": <num>, "hedging": <num>, "optimism": <num>},\n' ' "guidance": {"direction": "<RAISE|MAINTAIN|LOWER|WITHDRAWN>", ' '"revenue_delta_pct": <num>, "margin_delta_bps": <num>, "eps_delta_pct": <num>},\n' ' "qa_red_flags": [{"topic": <str>, "flag_type": <str>, "severity": <str>}],\n' ' "material_disclosures": [{"category": <str>, "materiality": <str>, ' '"quote": <str>}],\n' ' "analyst_action": "REVIEW_NOW | REVIEW_AM | FILE"\n' "}\n\n" "Set analyst_action=REVIEW_NOW if there is any HIGH-severity Q&A flag, " "any HIGH-materiality disclosure, or guidance_direction=LOWER. " "REVIEW_AM for MEDIUM signals. FILE otherwise. Do not fabricate any " "field — if a specialist returned nothing, leave the corresponding " "array empty or value null." ) def build_earnings_swarm(ticker: str, period: str, transcript: str, prior_qtr_guidance: str) -> dict: task = ( f"Analyze the {ticker} {period} earnings call. The full transcript " f"is below. The prior quarter's guidance section is included for " f"the Guidance Tracker. Each specialist runs their tool exactly " f"once and writes a short follow-up. The Synthesizer merges into " f"strict JSON per the schema.\n\n" f"=== TRANSCRIPT ({ticker} {period}) ===\n{transcript}\n\n" f"=== PRIOR QUARTER GUIDANCE ===\n{prior_qtr_guidance}" ) return { "name": f"Earnings Call Analysis - {ticker} {period}", "description": "Four specialists in parallel plus a Synthesizer.", "swarm_type": "ConcurrentWorkflow", "max_loops": 1, "task": task, "agents": [ { "agent_name": "Transcript Analyzer", "description": "Tone, confidence, hedging, forward optimism.", "system_prompt": TRANSCRIPT_ANALYZER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.2, "tools_list_dictionary": [SCORE_TONE_TOOL], }, { "agent_name": "Guidance Tracker", "description": "Quarter-over-quarter guidance delta.", "system_prompt": GUIDANCE_TRACKER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.1, "tools_list_dictionary": [COMPARE_GUIDANCE_TOOL], }, { "agent_name": "Q&A Sentiment", "description": "Deflection, hedging, and offline-followup detection.", "system_prompt": QA_SENTIMENT_PROMPT, "model_name": "claude-haiku-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": [EXTRACT_QA_RED_FLAGS_TOOL], }, { "agent_name": "Material Disclosure Detector", "description": "Reg FD-style material disclosure detection.", "system_prompt": MATERIAL_DISCLOSURE_PROMPT, "model_name": "claude-opus-4-8", "reasoning_effort": "high", "role": "worker", "max_loops": 1, "max_tokens": 3072, "temperature": 0.1, "tools_list_dictionary": [DETECT_MATERIAL_DISCLOSURE_TOOL], }, { "agent_name": "Synthesizer", "description": "Merges the four specialist outputs into one structured JSON note.", "system_prompt": SYNTHESIZER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.1, }, ], } ``` <Note> Function tools force structured outputs at the source, not at the synthesizer. By the time the Synthesizer reads the four specialist outputs, the tone scores, guidance deltas, and disclosure list are already typed JSON — the Synthesizer is just merging, not parsing free-form text. This is what makes the JSON contract reliable enough to feed straight into a Postgres or Snowflake table. </Note> ## Step 4: Process One Call End-to-End Start with a single transcript. This is the loop you scale. ```python theme={null} def run_one_call(ticker: str, period: str, transcript: str, prior_qtr_guidance: str) -> dict: payload = build_earnings_swarm(ticker, period, transcript, prior_qtr_guidance) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) response.raise_for_status() return response.json() def extract_synthesizer_json(swarm_result: dict) -> dict: # Single-call responses carry the conversation under "output"; # batch items carry it under "result". entries = swarm_result.get("output") or swarm_result.get("result") or [] text = "" for entry in entries: if "Synthesizer" in entry.get("role", ""): content = entry.get("content", "") if isinstance(content, list): content = " ".join(str(c) for c in content) text = str(content) break try: start = text.find("{") end = text.rfind("}") if start >= 0 and end > start: return json.loads(text[start:end + 1]) except json.JSONDecodeError: pass return {"parse_error": True, "raw": text} # Example — a single call. In practice the transcript and prior guidance # come from your filing feed (e.g. Quartr, AlphaSense, Bamsec). result = run_one_call( ticker="NVDA", period="Q3 2026", transcript=open("transcripts/NVDA_Q3_2026.txt").read(), prior_qtr_guidance=open("transcripts/NVDA_Q2_2026_guidance.txt").read(), ) note = extract_synthesizer_json(result) print(json.dumps(note, indent=2)) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` The Synthesizer output is the row you persist. The four specialist outputs are the audit trail — when a PM challenges the `REVIEW_NOW` flag on a portfolio name, you can trace it straight back to the verbatim quote the Material Disclosure Detector picked up. ## Step 5: Earnings-Season Batch Mode The single-call path is the prototype. The actual workload during peak earnings season is 125 calls a day. POST them to `/v1/swarm/batch/completions` in chunks of at most 50 — that is the per-request cap — and the API executes each chunk's swarms in parallel and returns one item per swarm shaped `{"status", "swarm_name", "result", "usage"}`. Items come back in submission order; matching them by `swarm_name` is the safer join once you are stitching several chunks together. ```python theme={null} def load_today_calls() -> list[dict]: """Return today's transcripts from your filing feed. Each row: {"ticker", "period", "transcript", "prior_qtr_guidance"}. """ return json.loads(Path("today_calls.json").read_text()) # /v1/swarm/batch/completions accepts at most 50 swarms per request. BATCH_SIZE_LIMIT = 50 def run_batch(calls: list[dict]) -> list[dict]: payload = [ build_earnings_swarm( c["ticker"], c["period"], c["transcript"], c["prior_qtr_guidance"], ) for c in calls ] results = [] for i in range(0, len(payload), BATCH_SIZE_LIMIT): response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload[i:i + BATCH_SIZE_LIMIT], timeout=3600, ) response.raise_for_status() results.extend(response.json()) return results def persist_and_alert(calls: list[dict], results: list[dict]) -> None: out_path = Path(f"notes_{datetime.utcnow().strftime('%Y%m%d')}.jsonl") review_now = [] # Batch items come back in submission order — join them back to the # input calls by swarm_name anyway, since the run spans several chunks. by_name = {r.get("swarm_name", ""): r for r in results} with out_path.open("w") as f: for call in calls: result = by_name.get( f"Earnings Call Analysis - {call['ticker']} {call['period']}", {} ) note = extract_synthesizer_json(result) note["_ticker"] = call["ticker"] note["_period"] = call["period"] f.write(json.dumps(note) + "\n") if note.get("analyst_action") == "REVIEW_NOW": review_now.append(note) if review_now and SLACK_URL: headline = ( f":rotating_light: {len(review_now)} of {len(calls)} calls " f"flagged REVIEW_NOW — see {out_path}" ) requests.post(SLACK_URL, json={"text": headline}, timeout=30) today = load_today_calls() print(f"Processing {len(today)} calls in batches of 50...") results = run_batch(today) persist_and_alert(today, results) total_cost = sum( r.get("usage", {}).get("billing_info", {}).get("total_cost", 0) for r in results ) print(f"Processed {len(results)} calls for ${total_cost:.2f}") ``` The crontab line that fires it at 5pm ET each weekday during the earnings burst: ```bash theme={null} # Earnings-season batch — 5:00 PM ET, weekdays 0 17 * * 1-5 cd /opt/swarms && /usr/bin/python earnings_batch.py >> /var/log/earnings.log 2>&1 ``` <Info> Most earnings calls during peak season land between 4:30pm and 5:00pm ET, immediately after the tape. Firing at 5:00pm ET catches the tail of late prints and gives the batch a clean window before market open the next morning. Premium-tier rate limits matter here: 125 ConcurrentWorkflows fired across three back-to-back 50-swarm batches consume meaningful concurrency, and queue contention on a free tier turns a 6-minute batch into a 90-minute one. The [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) guide covers the throughput tradeoffs in depth. </Info> ## Real Cost vs. Junior Analyst Per-call and per-day economics. The per-call number is the median across mixed-provider routing — Haiku on Q\&A is the lever that keeps the average down even when Opus 4.8 with reasoning runs on every disclosure check. | Scenario | Per call | Per day (125 calls) | Per 3-week earnings burst | | -------------------------------------------------------------------- | ------------ | ----------------------- | ------------------------- | | This swarm (4 specialists + synthesizer, mixed providers) | \~\$0.40 | \~\$50 | \~\$750 | | One sell-side analyst, fully loaded (\$300/hr blended, 1hr per call) | \~\$300 | \~\$2,400 (8 calls) | \~\$36,000 (8/day cap) | | Three-analyst sector pod | — | \~\$7,500 (24 calls) | \~\$112,500 (24/day cap) | | Full coverage by humans | not possible | \~\$37,500 of team time | \~\$562,500 | The hero number again: **by 4:45pm ET your DB has a structured note on every call — tone, guidance delta, red-flag Q\&A — for under \$50 a day.** The pipeline is not a replacement for the analyst's read on the names that move the book. It's the prep deck that makes sure no print on the sector slips through unnoticed during the three weeks of the year when humans physically cannot keep up. <Warning> Material disclosure detection is an assistive layer, not a compliance system of record. Every flag from the Material Disclosure Detector should land in a human reviewer queue before anything reaches an IR client or a portfolio decision. The verbatim quotes in the disclosure JSON are exactly the audit trail your compliance team will want to see. </Warning> ## Next Steps * [Build an AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) — the HierarchicalSwarm variant when you need a director synthesizing analyst briefs instead of fanning out in parallel * [Sell-Side Research Pipeline](/docs/examples/examples/sell-side-research-pipeline) — composing earnings notes, cited research, and reasoning agents into a single end-of-day deliverable (planned) * [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) — model routing, token budgeting, and batch scheduling patterns that keep the per-call number under a dollar at scale # ETF Analysis with Batched Grid Workflow Source: https://docs.swarms.ai/docs/examples/examples/etf-analysis-grid Fan two analyst agents across two tasks in parallel using BatchedGridWorkflow. ## What This Example Shows * The `BatchedGridWorkflow` endpoint, which runs every agent against every task in parallel * A practical financial-analysis use case: two ETF analysts (risk + quant) across two sector queries (energy + semis) * How to parse the per-task, per-agent output grid <Info> `BatchedGridWorkflow` is a fan-out × fan-out primitive. If you give it `N` agents and `M` tasks, you get `N × M` independent agent runs in parallel — perfect for "analyze each of these tickers using each of these specialists" workloads. </Info> ## Step 1: Setup ```python theme={null} import asyncio import os from typing import Any, Dict import httpx from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" ENDPOINT = f"{BASE_URL}/v1/batched-grid-workflow/completions" HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Build the Grid Two specialists, two tasks → four parallel agent runs. ```python theme={null} def build_payload() -> Dict[str, Any]: return { "name": "ETF Analysis Grid", "description": "Risk and quant analysis across energy and semiconductor ETFs.", "max_loops": 1, "agent_completions": [ { "agent_name": "Risk Analyst", "description": "Risk assessment and portfolio risk metrics.", "system_prompt": ( "You are a risk analyst specializing in ETF analysis. " "Evaluate ETFs based on volatility, downside risk, correlation, " "concentration risk, and risk-adjusted returns. Report Sharpe " "ratio, maximum drawdown, beta, and Value at Risk (VaR)." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Quantitative Analyst", "description": "Quantitative metrics and performance analysis.", "system_prompt": ( "You are a quantitative analyst specializing in ETF analysis. " "Evaluate ETFs on performance, expense ratios, tracking error, " "liquidity, and holdings composition. Provide returns, Sharpe " "ratio, information ratio, and factor exposures." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, ], "tasks": [ ( "Analyze the top energy ETFs including XLE, VDE, and IYE. Provide " "detailed risk and performance metrics, holdings analysis, and " "investment considerations." ), ( "Analyze the top semiconductor ETFs including SMH, SOXX, and XSD. " "Provide detailed risk and performance metrics, holdings analysis, " "and investment considerations." ), ], } ``` ## Step 3: Call the Endpoint The `/v1/batched-grid-workflow/completions` endpoint is async-friendly. Use `httpx.AsyncClient` to avoid blocking your event loop. ```python theme={null} async def run_grid() -> Dict[str, Any]: async with httpx.AsyncClient(timeout=300.0) as client: response = await client.post(ENDPOINT, headers=HEADERS, json=build_payload()) response.raise_for_status() return response.json() ``` ## Step 4: Parse the Output The response carries one entry per task; each entry is a dict keyed by agent name. ```python theme={null} def show(response_data: Dict[str, Any]) -> None: for task_idx, task_outputs in enumerate(response_data.get("outputs", []), start=1): print("=" * 60) print(f"Task {task_idx}") print("=" * 60) if isinstance(task_outputs, dict): for agent_name, agent_response in task_outputs.items(): print(f"\n--- {agent_name} ---") print(str(agent_response)[:400] + "...") if __name__ == "__main__": response = asyncio.run(run_grid()) show(response) ``` <Note> Output shape: `outputs[task_index][agent_name] = response`. If you flatten this into a 2-D grid (rows = tasks, columns = agents), every cell is an independent analyst opinion you can compare side-by-side. </Note> ## When To Use Batched Grid | If you need… | Use | | ------------------------------------------------ | ------------------------- | | Each agent to see the previous agent's output | `SequentialWorkflow` | | All agents to react to the same task in parallel | `ConcurrentWorkflow` | | Same agents applied to many independent tasks | **`BatchedGridWorkflow`** | | A director to synthesize specialist opinions | `HierarchicalSwarm` | Batched Grid is the right choice when each task is independent — no shared state, no inter-agent communication, just maximum parallelism. <Warning> `BatchedGridWorkflow` is a premium endpoint. See the [pricing page](/docs/documentation/resources/pricing) for cost details. </Warning> # Graph Workflow Example Source: https://docs.swarms.ai/docs/examples/examples/graph-workflow Build a content creation pipeline with Graph Workflow ## Content Creation Pipeline with Graph Structure This example demonstrates how to build a complex content workflow using a directed graph - perfect for workflows that need both parallel processing and sequential dependencies. <Warning> Premium: Graph Workflow is available only on Pro, Ultra, and Premium plans. See [Pricing](/docs/documentation/resources/pricing). </Warning> ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Ensure you have a Pro or Ultra plan 4. Generate a new API key 5. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define Your Graph Workflow Create a content pipeline where research happens in parallel, then flows into writing, editing, and finally SEO: ```python theme={null} def create_blog_post(topic: str) -> dict: """ Create a blog post using a graph workflow. Graph structure: [Research A] ──┐ [Research B] ──┼──> [Writer] ──> [Editor] ──> [SEO Optimizer] [Research C] ──┘ """ workflow_config = { "name": "Blog Post Creation Pipeline", "description": "Graph workflow for creating SEO-optimized blog posts", "task": f"Create a comprehensive blog post about: {topic}", "agents": [ { "agent_name": "Tech Researcher", "description": "Researches technical aspects", "system_prompt": "You are a technical researcher. Research technical details, innovations, and implementations related to the topic.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Market Researcher", "description": "Researches market trends", "system_prompt": "You are a market researcher. Research market trends, statistics, industry adoption, and business implications.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Case Study Researcher", "description": "Finds real-world examples", "system_prompt": "You are a case study researcher. Find real-world examples, success stories, and practical applications of the topic.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Content Writer", "description": "Writes the blog post", "system_prompt": "You are a content writer. Synthesize all research into an engaging, well-structured 1500-word blog post with clear sections and examples.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6 }, { "agent_name": "Editor", "description": "Edits and polishes content", "system_prompt": "You are an editor. Review for clarity, grammar, flow, and readability. Improve structure and ensure professional quality.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "SEO Specialist", "description": "Optimizes for search engines", "system_prompt": "You are an SEO specialist. Add: meta description, keywords, optimize headings, add internal linking suggestions, and ensure SEO best practices.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "edges": [ # Parallel research phase - all three researchers work independently {"source": "Tech Researcher", "target": "Content Writer"}, {"source": "Market Researcher", "target": "Content Writer"}, {"source": "Case Study Researcher", "target": "Content Writer"}, # Sequential editing phase {"source": "Content Writer", "target": "Editor"}, {"source": "Editor", "target": "SEO Specialist"} ], "entry_points": ["Tech Researcher", "Market Researcher", "Case Study Researcher"], "end_points": ["SEO Specialist"], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_config, timeout=180 ) return response.json() ``` ### Step 4: Run the Workflow ```python theme={null} # Topic for the blog post topic = "The Future of AI in Healthcare: Opportunities and Challenges" # Run the graph workflow result = create_blog_post(topic) # Display results in execution order print(f"Workflow: {result['name']}") print(f"Status: {result['status']}\n") # Show outputs by workflow stage stages = [ ["Tech Researcher", "Market Researcher", "Case Study Researcher"], ["Content Writer"], ["Editor"], ["SEO Specialist"] ] for stage_num, stage_agents in enumerate(stages, 1): print(f"\n{'='*60}") print(f"STAGE {stage_num}: {', '.join(stage_agents)}") print('='*60) for agent_name in stage_agents: if agent_name in result['outputs']: output = result['outputs'][agent_name] # Handle output as string or list if isinstance(output, list): output = ' '.join(str(item) for item in output) print(f"\n[{agent_name}]") print(str(output)[:300] + "...\n") # Display cost info (the graph-workflow endpoint returns a flat `usage` # object with `token_cost`, not the nested `billing_info` shape used by # /v1/swarm/completions) usage = result.get('usage', {}) if 'token_cost' in usage: print(f"\nTotal cost: ${usage['token_cost']:.4f}") else: print(f"\nTotal cost: Not available") ``` **Expected Output:** ``` Workflow: Blog Post Creation Pipeline Status: success ============================================================ STAGE 1: Tech Researcher, Market Researcher, Case Study Researcher ============================================================ [Tech Researcher] Technical innovations in AI healthcare include: 1. **Diagnostic AI**: Deep learning models achieving 95%+ accuracy in medical imaging 2. **Drug Discovery**: AI reducing discovery time from 5 years to 18 months 3. **Personalized Medicine**: ML algorithms analyzing genetic data for custom treatments 4. **Robotic Surgery**: AI-assisted procedures with 40% less complications... [Market Researcher] Healthcare AI Market Analysis: **Market Size**: $15.1B (2024) → $187.9B (2030) - 51.9% CAGR **Key Drivers**: Aging population, chronic disease prevalence, physician shortages **Top Adopters**: Radiology (68%), Pathology (54%), Oncology (49%) **Regional Leaders**: North America (42%), Europe (28%), Asia-Pacific (23%)... [Case Study Researcher] Real-World AI Healthcare Success Stories: **Case 1: Mayo Clinic - Early Disease Detection** Implementation: AI analyzing ECG data to detect heart disease 10 years earlier Results: 85% accuracy, 30,000+ patients screened, 15% reduction in cardiac events... ============================================================ STAGE 2: Content Writer ============================================================ [Content Writer] # The Future of AI in Healthcare: Opportunities and Challenges The healthcare industry stands at the cusp of a technological revolution. Artificial intelligence is not just changing how we diagnose and treat diseases—it's fundamentally transforming the entire healthcare ecosystem... [1500-word article synthesizing all research with proper structure, examples, and citations] ============================================================ STAGE 3: Editor ============================================================ [Editor] **Edited Version with Improvements:** # The Future of AI in Healthcare: Opportunities and Challenges [Refined article with improved flow, corrected grammar, enhanced readability, and professional polish. Added transition sentences, clarified technical terms, and ensured consistent tone throughout.] Key improvements made: - Restructured intro for stronger hook - Clarified technical jargon - Added transition sentences - Improved conclusion... ============================================================ STAGE 4: SEO Specialist ============================================================ [SEO Specialist] **SEO-Optimized Final Version:** **Meta Title**: AI in Healthcare: 2025 Opportunities, Challenges & Future Trends **Meta Description**: Discover how AI is transforming healthcare in 2025. Explore diagnostic AI, personalized medicine, real case studies, and future trends. Expert analysis included. **Primary Keywords**: AI in healthcare, artificial intelligence healthcare, healthcare AI trends **Secondary Keywords**: medical AI, diagnostic AI, personalized medicine AI **Optimized Headings**: H1: The Future of AI in Healthcare: Opportunities and Challenges H2: How AI is Revolutionizing Medical Diagnostics H2: Real-World Success Stories: AI in Action H2: Challenges and Ethical Considerations H2: The Road Ahead: AI Healthcare in 2030 **Internal Linking Suggestions**: - Link to "Machine Learning in Medicine" article - Link to "Healthcare Data Privacy" guide - Link to "AI Ethics" resource page... Total cost: $0.1456 ``` <Note> Graph Workflow allows you to define complex dependencies: * **Parallel execution**: Multiple researchers work simultaneously * **Sequential dependencies**: Writer waits for all research, Editor waits for Writer * **Clear flow**: Entry points → Processing → End points Use edges to define how data flows between agents. </Note> ## Graph Structure Visualization ```mermaid theme={null} graph TD A[Tech Researcher<br/>Entry Point] --> D[Content Writer] B[Market Researcher<br/>Entry Point] --> D C[Case Study Researcher<br/>Entry Point] --> D D --> E[Editor] E --> F[SEO Specialist<br/>End Point] style A fill:# style B fill:# style C fill:# style F fill:# ``` *** ## Software Code Review Pipeline This example demonstrates a parallel code review pipeline where three specialized reviewers (code quality, security, performance) analyze code simultaneously, then a synthesizer produces a unified go/no-go recommendation. **Graph structure:** ``` [CodeAnalyzer] ──┐ [SecurityAuditor] ──┼──> [ReviewSynthesizer] [PerformanceReviewer]──┘ ``` ```python theme={null} def review_code(code_snippet: str) -> dict: """ Run parallel code review with specialized reviewers. Graph structure: [CodeAnalyzer] ──┐ [SecurityAuditor] ──┼──> [ReviewSynthesizer] [PerformanceReviewer]──┘ """ workflow_config = { "name": "Code-Review-Pipeline", "description": "Parallel code review with specialized reviewers converging into a synthesis report", "task": f"Review the following code:\n\n{code_snippet}", "agents": [ { "agent_name": "CodeAnalyzer", "description": "Analyzes code structure, logic, and design patterns", "system_prompt": "You are a senior software engineer specializing in code analysis. Review code for correctness, design patterns, and maintainability. Identify potential bugs, anti-patterns, and suggest improvements.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "SecurityAuditor", "description": "Audits code for security vulnerabilities", "system_prompt": "You are a cybersecurity expert. Audit the code for security vulnerabilities including injection attacks, authentication flaws, data exposure, and OWASP Top 10 issues. Provide severity ratings and remediation steps.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.1, "max_loops": 1, }, { "agent_name": "PerformanceReviewer", "description": "Reviews code for performance issues", "system_prompt": "You are a performance engineering expert. Analyze code for performance bottlenecks, memory leaks, inefficient algorithms, and scalability issues. Suggest concrete optimizations with expected impact.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "ReviewSynthesizer", "description": "Synthesizes all review findings into a unified report", "system_prompt": "You are a tech lead. Synthesize findings from code analysis, security audit, and performance review into a single prioritized action plan. Categorize issues by severity (critical, major, minor) and provide a clear go/no-go recommendation.", "model_name": "gpt-4.1", "max_tokens": 5000, "temperature": 0.3, "max_loops": 1, }, ], "edges": [ {"source": "CodeAnalyzer", "target": "ReviewSynthesizer"}, {"source": "SecurityAuditor", "target": "ReviewSynthesizer"}, {"source": "PerformanceReviewer", "target": "ReviewSynthesizer"}, ], "entry_points": ["CodeAnalyzer", "SecurityAuditor", "PerformanceReviewer"], "end_points": ["ReviewSynthesizer"], "max_loops": 1, } response = requests.post( f"{API_BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_config, timeout=300 ) return response.json() # Example: Review a Flask login endpoint code = ''' import sqlite3 from flask import Flask, request, jsonify import hashlib app = Flask(__name__) @app.route('/login', methods=['POST']) def login(): username = request.form['username'] password = request.form['password'] conn = sqlite3.connect('users.db') cursor = conn.cursor() query = f"SELECT * FROM users WHERE username='{username}' AND password='{hashlib.md5(password.encode()).hexdigest()}'" cursor.execute(query) user = cursor.fetchone() conn.close() if user: return jsonify({'status': 'success', 'token': hashlib.md5(username.encode()).hexdigest()}) return jsonify({'status': 'failed'}), 401 ''' result = review_code(code) print(f"Workflow: {result['name']}") print(f"Status: {result['status']}\n") # Show each reviewer's findings then the synthesis reviewers = ["CodeAnalyzer", "SecurityAuditor", "PerformanceReviewer", "ReviewSynthesizer"] for agent_name in reviewers: if agent_name in result['outputs']: output = result['outputs'][agent_name] if isinstance(output, list): output = ' '.join(str(item) for item in output) print(f"\n{'='*60}") print(f"[{agent_name}]") print('='*60) print(str(output)[:300] + "...") ``` **Expected Output:** ``` Workflow: Code-Review-Pipeline Status: success ============================================================ [CodeAnalyzer] ============================================================ Code Analysis Report: 1. **SQL Injection (Critical)**: f-string SQL query construction allows arbitrary SQL injection 2. **Weak Hashing**: MD5 is cryptographically broken for password hashing 3. **No Input Validation**: Missing input sanitization on username/password 4. **Connection Management**: No context manager for database connection... ============================================================ [SecurityAuditor] ============================================================ Security Audit Report — OWASP Top 10 Mapping: **CRITICAL — A03:2021 Injection (Score: 10/10)** SQL injection via f-string query. Attacker can bypass auth with: username=' OR '1'='1 **CRITICAL — A02:2021 Cryptographic Failures (Score: 9/10)** MD5 is broken. Use bcrypt or argon2 with salting... ============================================================ [PerformanceReviewer] ============================================================ Performance Review: 1. **Database Connection Per Request**: Creating new SQLite connection each call — use connection pooling 2. **No Index Guarantee**: Query assumes index on username column 3. **Full Row Select**: SELECT * fetches unnecessary columns... ============================================================ [ReviewSynthesizer] ============================================================ Unified Code Review — Verdict: NO-GO **Critical Issues (must fix before merge):** 1. SQL Injection vulnerability (Security) 2. MD5 password hashing (Security) 3. Predictable session tokens (Security) **Major Issues:** 1. No input validation (Code Quality) 2. No connection pooling (Performance)... ``` <Note> This pattern is ideal for **automated CI/CD code review** — all three reviewers run in parallel so the total latency is only as long as the slowest reviewer, not the sum of all three. </Note> *** ## Multi-Language Content Localization (Multiple End Points) This example demonstrates a fan-out workflow with **multiple end points** — a content strategist creates source content, which fans out to three translators running in parallel. Each translator is an independent end point. **Graph structure:** ``` ┌──> [SpanishTranslator] (End Point) [ContentStrategist] ┼──> [JapaneseTranslator] (End Point) └──> [GermanTranslator] (End Point) ``` ```python theme={null} def localize_content(brief: str) -> dict: """ Create content and localize it into multiple languages in parallel. Graph structure: ┌──> [SpanishTranslator] [ContentStrategist] ┼──> [JapaneseTranslator] └──> [GermanTranslator] """ workflow_config = { "name": "Content-Localization-Pipeline", "description": "Fan-out localization: one source feeding multiple translators in parallel", "task": brief, "agents": [ { "agent_name": "ContentStrategist", "description": "Creates source content and localization guidelines", "system_prompt": "You are a content strategist. Create clear, culturally-neutral source content and provide localization guidelines including tone, key terms to preserve, and cultural adaptation notes.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.4, "max_loops": 1, }, { "agent_name": "SpanishTranslator", "description": "Translates and localizes for Spanish-speaking markets", "system_prompt": "You are an expert Spanish translator and localization specialist. Translate the content you receive into natural Latin American Spanish. Adapt cultural references and idioms for Spanish-speaking audiences. Output only the translated content.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "JapaneseTranslator", "description": "Translates and localizes for Japanese market", "system_prompt": "You are an expert Japanese translator and localization specialist. Translate the content you receive into natural Japanese, using appropriate formality levels (keigo where needed). Output only the translated content.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "GermanTranslator", "description": "Translates and localizes for German-speaking markets", "system_prompt": "You are an expert German translator and localization specialist. Translate the content you receive into natural German (Hochdeutsch). Handle compound nouns appropriately. Output only the translated content.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, ], "edges": [ {"source": "ContentStrategist", "target": "SpanishTranslator"}, {"source": "ContentStrategist", "target": "JapaneseTranslator"}, {"source": "ContentStrategist", "target": "GermanTranslator"}, ], "entry_points": ["ContentStrategist"], "end_points": ["SpanishTranslator", "JapaneseTranslator", "GermanTranslator"], "max_loops": 1, } response = requests.post( f"{API_BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_config, timeout=300 ) return response.json() # Localize a product launch announcement result = localize_content( "Create and localize a product launch announcement for an AI-powered project management " "tool called 'FlowBoard'. The tool features smart task prioritization, natural language " "project updates, and automated sprint planning. Target audience: tech-savvy project " "managers and team leads." ) print(f"Workflow: {result['name']}") print(f"Status: {result['status']}\n") # Show source content then each translation agents_order = ["ContentStrategist", "SpanishTranslator", "JapaneseTranslator", "GermanTranslator"] labels = {"ContentStrategist": "SOURCE (English)", "SpanishTranslator": "SPANISH", "JapaneseTranslator": "JAPANESE", "GermanTranslator": "GERMAN"} for agent_name in agents_order: if agent_name in result['outputs']: output = result['outputs'][agent_name] if isinstance(output, list): output = ' '.join(str(item) for item in output) print(f"\n{'='*60}") print(f"{labels[agent_name]}") print('='*60) print(str(output)[:400] + "...") ``` **Expected Output:** ``` Workflow: Content-Localization-Pipeline Status: success ============================================================ SOURCE (English) ============================================================ Product Launch Announcement — FlowBoard Subject: Introducing FlowBoard: The Smarter Way to Manage Projects Dear Project Leaders, We are excited to announce the launch of FlowBoard, an AI-powered project management platform designed to transform how teams plan, track, and deliver projects... ============================================================ SPANISH ============================================================ Anuncio de Lanzamiento — FlowBoard Asunto: Presentamos FlowBoard: La Forma Más Inteligente de Gestionar Proyectos Estimados Líderes de Proyecto, Nos complace anunciar el lanzamiento de FlowBoard, una plataforma de gestión de proyectos impulsada por inteligencia artificial... ============================================================ JAPANESE ============================================================ 製品発表のお知らせ — FlowBoard 件名:FlowBoard のご紹介:よりスマートなプロジェクト管理を実現 プロジェクトリーダーの皆様へ FlowBoard の正式リリースをお知らせいたします。FlowBoard は、AI を活用した プロジェクト管理プラットフォームです... ============================================================ GERMAN ============================================================ Produktankündigung — FlowBoard Betreff: Wir stellen vor: FlowBoard – Die intelligentere Art, Projekte zu verwalten Sehr geehrte Projektverantwortliche, wir freuen uns, die Einführung von FlowBoard bekannt zu geben, einer KI-gestützten Projektmanagement-Plattform... ``` <Note> This pattern showcases **multiple end points** — unlike most examples where outputs converge, here the graph fans out and each translator is an independent terminal node. This is perfect for localization, A/B test generation, or multi-format content creation. </Note> *** ## Financial Due Diligence Pipeline This example demonstrates a multi-stage pipeline where parallel analysis feeds into sequential decision-making — two analysts work in parallel, their findings converge into a risk assessor, which then feeds an investment committee for a final recommendation. **Graph structure:** ``` [FinancialAnalyst] ──┐ ├──> [RiskAssessor] ──> [InvestmentCommittee] [MarketAnalyst] ──┘ ``` ```python theme={null} def run_due_diligence(company_brief: str) -> dict: """ Run investment due diligence with parallel analysis and sequential decision-making. Graph structure: [FinancialAnalyst] ──┐ ├──> [RiskAssessor] ──> [InvestmentCommittee] [MarketAnalyst] ──┘ """ workflow_config = { "name": "Financial-Due-Diligence-Pipeline", "description": "Multi-stage due diligence: parallel analysis → risk assessment → investment decision", "task": company_brief, "agents": [ { "agent_name": "FinancialAnalyst", "description": "Analyzes financial statements and metrics", "system_prompt": "You are a financial analyst. Analyze financial statements, calculate key ratios (P/E, debt-to-equity, ROE, profit margins), and assess financial health. Provide quantitative analysis with specific numbers.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "MarketAnalyst", "description": "Evaluates market position and competitive landscape", "system_prompt": "You are a market analyst. Evaluate market position, competitive landscape, TAM/SAM/SOM, market trends, and growth potential. Provide data-driven market assessment.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "RiskAssessor", "description": "Identifies and quantifies risks from financial and market analyses", "system_prompt": "You are a risk assessment specialist. Using the financial and market analyses, identify and quantify key risks: market risk, operational risk, regulatory risk, and concentration risk. Assign risk scores (1-10) and provide mitigation strategies.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "InvestmentCommittee", "description": "Makes final investment recommendation", "system_prompt": "You are an investment committee chair. Synthesize all financial analysis, market assessment, and risk evaluation into a final investment recommendation. Provide a clear BUY/HOLD/PASS verdict with target valuation range, key conditions, and monitoring triggers.", "model_name": "gpt-4.1", "max_tokens": 5000, "temperature": 0.3, "max_loops": 1, }, ], "edges": [ {"source": "FinancialAnalyst", "target": "RiskAssessor"}, {"source": "MarketAnalyst", "target": "RiskAssessor"}, {"source": "RiskAssessor", "target": "InvestmentCommittee"}, ], "entry_points": ["FinancialAnalyst", "MarketAnalyst"], "end_points": ["InvestmentCommittee"], "max_loops": 1, } response = requests.post( f"{API_BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_config, timeout=300 ) return response.json() # Run due diligence on a hypothetical company result = run_due_diligence( "Conduct due diligence analysis on a Series B SaaS company 'DataSync AI' seeking $50M " "at a $400M valuation. The company has $12M ARR growing 120% YoY, 85% gross margins, " "-$3M net income, 140% net revenue retention, 1,200 enterprise customers, and operates " "in the data integration market competing against Fivetran and Airbyte." ) print(f"Workflow: {result['name']}") print(f"Status: {result['status']}\n") # Show the pipeline stages stages = [ ("STAGE 1 — Parallel Analysis", ["FinancialAnalyst", "MarketAnalyst"]), ("STAGE 2 — Risk Assessment", ["RiskAssessor"]), ("STAGE 3 — Investment Decision", ["InvestmentCommittee"]), ] for stage_label, agent_names in stages: print(f"\n{'='*60}") print(stage_label) print('='*60) for agent_name in agent_names: if agent_name in result['outputs']: output = result['outputs'][agent_name] if isinstance(output, list): output = ' '.join(str(item) for item in output) print(f"\n[{agent_name}]") print(str(output)[:300] + "...") ``` **Expected Output:** ``` Workflow: Financial-Due-Diligence-Pipeline Status: success ============================================================ STAGE 1 — Parallel Analysis ============================================================ [FinancialAnalyst] Financial Analysis — DataSync AI (Series B) **Revenue Metrics:** - ARR: $12M | YoY Growth: 120% | Implied MRR: $1M - Net Revenue Retention: 140% (best-in-class) - Gross Margin: 85% (strong SaaS economics) **Profitability:** - Net Income: -$3M | Implied Burn Rate: ~$15M/year - Runway with $50M raise: ~3+ years at current burn... [MarketAnalyst] Market Assessment — Data Integration Space **TAM/SAM/SOM:** - TAM: $15.6B (global data integration market, 2024) - SAM: $4.2B (cloud-native data integration) - SOM: $840M (AI-powered segment) **Competitive Landscape:** - Fivetran: $1.2B+ valuation, 5,000+ customers, established leader - Airbyte: Open-source approach, strong developer community... ============================================================ STAGE 2 — Risk Assessment ============================================================ [RiskAssessor] Risk Assessment Matrix — DataSync AI | Risk Category | Score (1-10) | Key Factors | |-----------------|-------------|-------------------------------------| | Market Risk | 5 | Strong TAM but intense competition | | Operational Risk| 6 | Negative net income, scaling needs | | Regulatory Risk | 3 | Standard SaaS data handling | | Concentration | 4 | 1,200 customers, reasonable spread | **Overall Risk Score: 4.5/10 (Moderate)**... ============================================================ STAGE 3 — Investment Decision ============================================================ [InvestmentCommittee] Investment Committee Recommendation — DataSync AI Series B **Verdict: CONDITIONAL BUY** **Valuation Assessment:** - $400M at $12M ARR = 33x ARR multiple - Justified by: 120% growth, 140% NRR, 85% gross margins - Target range: $350M-$450M (fair at midpoint) **Key Conditions:** 1. Path to profitability within 18 months 2. Customer concentration analysis (top 10 < 30% of ARR) 3. Technical differentiation audit vs. Fivetran/Airbyte... ``` <Note> This pattern demonstrates a **multi-stage DAG** — parallel entry points feed a middle layer, which feeds the final decision node. Each stage builds on the outputs of the previous stage. The `RiskAssessor` has access to both the financial and market analyses before it runs, and the `InvestmentCommittee` sees everything. </Note> *** ## When to Use Graph Workflow * **Complex dependencies**: Some agents depend on multiple others * **Parallel + Sequential**: Mix parallel and sequential processing * **Multiple entry/exit points**: Workflows with multiple starts or ends * **DAG structures**: Any directed acyclic graph workflow ## Pattern Comparison | Pattern | Best For | Structure | | ---------------- | ----------------------------------------------- | -------------------------------- | | **Graph** | Complex dependencies, mixed parallel/sequential | Custom directed graph with edges | | **Hierarchical** | Coordination and oversight | Leader + Workers | | **Sequential** | Step-by-step pipeline | Linear chain | | **Concurrent** | Independent parallel tasks | All agents run at once | # Graph Workflow Edge Formats Reference Source: https://docs.swarms.ai/docs/examples/examples/graph-workflow-edge-formats The supported edge syntaxes for the Swarms Graph Workflow endpoint — dict form and dict with metadata — plus the list forms the API rejects, with side-by-side examples building the same DAG. ## What This Example Shows * Both edge syntaxes the Graph Workflow endpoint actually accepts — and the list/tuple forms it rejects * Side-by-side examples where each format produces the same three-agent DAG * How to express multi-target (fan-out) edges and conditional gating * A summary table for picking the right format for the job * One end-to-end runnable workflow that mixes formats in a single `edges` array <Warning> The Graph Workflow endpoint (`POST /v1/graph-workflow/completions`) is a premium-only feature available on Pro, Ultra, and Premium plans. Free-tier keys receive a 403. [Upgrade your account](https://swarms.world/platform/account) to run production DAGs. </Warning> ## Why This Matters Most teams adopt Graph Workflow with one edge format in mind — usually the dict form `{"source": "A", "target": "B"}` — then run into friction when their DAG grows or when ops needs to tag specific edges. The API accepts two interchangeable formats: the plain dict form and the dict form with a `metadata` block. List and tuple shorthands like `["A", "B"]` are rejected by request validation before the workflow runs. This reference walks each accepted format end to end against the same target DAG so you can see the trade-offs in one place, and shows how to compose multi-target fan-outs and prompt-level conditional gating without inventing a syntax the API doesn't actually support. ## Step 1: Setup Install dependencies and load your API key. ```bash theme={null} pip install requests python-dotenv ``` ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } ``` ## Step 2: Define the Shared Agent Pool Every example below reuses the same three-agent pool so only the edges change between formats. ```python theme={null} agents = [ { "agent_name": "Agent1", "description": "First agent in the workflow", "system_prompt": "You are Agent 1. Process the initial task.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "Agent2", "description": "Second agent in the workflow", "system_prompt": "You are Agent 2. Process data from Agent 1.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "Agent3", "description": "Third agent in the workflow", "system_prompt": "You are Agent 3. Process data from Agent 2.", "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, ] ``` The baseline target DAG for both formats is the same linear pipeline: ```text theme={null} [Agent1] --> [Agent2] --> [Agent3] ``` ## Step 3: Format 1 — Dict Form The canonical and most common format. Each edge is a dictionary with explicit `source` and `target` keys. Verbose but extremely readable in code reviews — most production codebases standardize on this. ```python theme={null} edges_dict = [ {"source": "Agent1", "target": "Agent2"}, {"source": "Agent2", "target": "Agent3"}, ] workflow_input = { "name": "Edge-Format-1-Dict", "description": "Linear pipeline declared with explicit dict edges.", "agents": agents, "edges": edges_dict, "entry_points": ["Agent1"], "end_points": ["Agent3"], "max_loops": 1, "task": "Process a simple task through a three-agent pipeline.", "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() print(response.json().get("status")) ``` ## Step 4: Format 2 — Dict with Metadata The dict form plus an optional `metadata` field — a free-form dictionary you can attach to any edge for routing hints, priority labels, telemetry tags, retry policies, or downstream business rules. The metadata travels with the edge through the compiler. ```python theme={null} edges_dict_metadata = [ { "source": "Agent1", "target": "Agent2", "metadata": { "priority": "high", "data_type": "processed_data", }, }, { "source": "Agent2", "target": "Agent3", "metadata": { "priority": "high", "data_type": "processed_data", "audit_tag": "regulated", }, }, ] workflow_input = { "name": "Edge-Format-2-Dict-Metadata", "description": "Linear pipeline with metadata attached to every edge.", "agents": agents, "edges": edges_dict_metadata, "entry_points": ["Agent1"], "end_points": ["Agent3"], "max_loops": 1, "task": "Process a simple task through a three-agent pipeline with edge metadata.", "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() print(response.json().get("status")) ``` <Note> Metadata keys are unconstrained — use whatever your ops or audit tooling expects. Common patterns: `priority`, `retry_on_failure`, `audit_tag`, `data_type`, `timeout`, `cost_center`. See [Tagging Graph Workflow Edges with Metadata](/docs/examples/examples/graph-workflow-metadata) for the full production playbook. </Note> ## Step 5: List and Tuple Edges Are Rejected Each edge in the request schema must be an object (an `EdgeSpec` or a dictionary with `source` and `target` keys). Terse list shorthands — `[source, target]` or `[source, target, metadata]`, and their Python tuple equivalents — fail request validation with a `422 Unprocessable Entity` before the workflow ever runs. ```python theme={null} # These payloads are REJECTED with a 422 validation error: edges_list = [ ["Agent1", "Agent2"], ["Agent2", "Agent3"], ] edges_list_metadata = [ ["Agent1", "Agent2", {"priority": "high", "data_type": "processed_data"}], ["Agent2", "Agent3", {"priority": "high", "audit_tag": "regulated"}], ] # The accepted equivalents: edges = [ {"source": "Agent1", "target": "Agent2"}, {"source": "Agent2", "target": "Agent3", "metadata": {"audit_tag": "regulated"}}, ] ``` If you prefer writing arrow-like pairs in your own code, keep them as local shorthand and convert before submission: ```python theme={null} pairs = [("Agent1", "Agent2"), ("Agent2", "Agent3")] edges = [{"source": s, "target": t} for s, t in pairs] ``` ## Step 6: Multi-Target (Fan-Out) Edges There is no dedicated multi-target syntax in the API — you express a fan-out by writing one edge per downstream target, all sharing the same source. The compiler builds the parallel branches and runs them concurrently. This is the same expressive power as a hypothetical `"A -> [B, C]"` shorthand, just stated explicitly. ```python theme={null} # Agent1 fans out to Agent2 and Agent3 in parallel. edges_fanout = [ {"source": "Agent1", "target": "Agent2"}, {"source": "Agent1", "target": "Agent3"}, ] workflow_input = { "name": "Edge-Format-Fan-Out", "description": "Fan-out from one source to two parallel downstream targets.", "agents": agents, "edges": edges_fanout, "entry_points": ["Agent1"], "end_points": ["Agent2", "Agent3"], "max_loops": 1, "task": "Send the same input to two downstream agents in parallel.", "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() print(response.json().get("status")) ``` The same trick scales — N edges with the same `source` produce an N-way fan-out, and N edges with the same `target` produce an N-way fan-in. The full DAG is just a list of pairwise edges; structure emerges from the edge set. ## Step 7: Conditional Edges via Prompt-Level Gating The Graph Workflow endpoint does not expose a schema-level `condition` field on edges — every declared edge fires when its upstream node completes. To implement a conditional path, encode the gate in the downstream node's prompt: ```python theme={null} gated_agents = [ { "agent_name": "Triage", "description": "Decides whether to escalate or pass through.", "system_prompt": ( "You are a triage agent. Inspect the input and output exactly one " "token at the end of your response: `ESCALATE` if the situation " "warrants escalation, otherwise `PASS`. Be conservative — only " "escalate on clear signals." ), "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.1, "max_loops": 1, }, { "agent_name": "HumanEscalation", "description": "Drafts an escalation note for a human operator.", "system_prompt": ( "You receive an upstream Triage agent's output. If the upstream " "output ends with `PASS`, respond with the single token `SKIPPED` " "and stop. If it ends with `ESCALATE`, draft a 3-bullet escalation " "note for a human operator." ), "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.2, "max_loops": 1, }, ] gated_edges = [ {"source": "Triage", "target": "HumanEscalation"}, ] ``` The `HumanEscalation` node runs every time, but produces a `SKIPPED` no-op when the upstream emits `PASS`. Downstream consumers (or a final synthesis node) check for `SKIPPED` and ignore the branch. See [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) for the full SKIP-gating pattern in a real DAG. ## Step 8: Mix Formats in One Workflow The API accepts heterogeneous edges in the same `edges` array. Sketch the trunk of the graph with plain dict edges and add a `metadata` block only on the edges ops actually cares about. ```python theme={null} edges_mixed = [ {"source": "Agent1", "target": "Agent2"}, # plain dict for a routine link { "source": "Agent2", "target": "Agent3", "metadata": { "audit_tag": "regulatory", "priority": "high", }, }, # dict-with-metadata for the regulated step ] workflow_input = { "name": "Edge-Format-Mixed", "description": "Mixed-format edges in a single workflow.", "agents": agents, "edges": edges_mixed, "entry_points": ["Agent1"], "end_points": ["Agent3"], "max_loops": 1, "task": "Process a simple task through a three-agent pipeline.", "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() print(response.json().get("status")) ``` ## Step 9: Read the Per-Node Output Regardless of which edge format you submit, the response shape is identical. Outputs are keyed by `agent_name`. ```python theme={null} result = response.json() outputs = result.get("outputs", {}) for name in ["Agent1", "Agent2", "Agent3"]: if name in outputs: print(f"\n[{name}]") print(str(outputs[name])[:300]) usage = result.get("usage", {}) print(f"\nTotal cost: ${usage.get('token_cost', 0):.4f}") print(f"Total tokens: {usage.get('total_tokens', 0)}") ``` ## Choosing the Right Format | Format | Best for | Pros | Cons | | ---------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------- | --------------------------------------------------------- | | **Dict form** `{"source": ..., "target": ...}` | Most production codebases | Explicit, lints cleanly, easy to refactor | Verbose for large graphs | | **Dict with metadata** | Edges that need routing hints, audit labels, or retry policy | Carries ops and business context with the edge | Most verbose; only worth it when you consume the metadata | | **List/tuple forms** `[source, target]` | Not accepted — rejected with a 422 | — | Convert to dict form before submission | | **Multi-target fan-out** | One upstream feeding many parallel downstreams | Pure composition — no new syntax | Verbose for very wide fan-outs | | **Conditional gating** | Skipping branches based on upstream signal | No new syntax; pure prompt engineering | Downstream node still consumes tokens to emit `SKIPPED` | <Info> A common production convention: use the plain dict form everywhere, and add a `metadata` block only on edges that participate in audit, retry, or routing logic. </Info> ## Common Pitfalls <AccordionGroup> <Accordion title="422 error: edge fails request validation"> The API expects each edge to be an object — an `EdgeSpec` or a dict with `source` and `target` keys. List/tuple shorthands like `["Agent1", "Agent2"]` and strings like `"Agent1 -> Agent2"` are rejected with a 422 before the workflow runs. Convert them to the dict form. </Accordion> <Accordion title="400 error: `source node '...' does not exist`"> Every edge's `source` and `target` must match an `agent_name` in the `agents` array exactly. Watch for whitespace, casing, and trailing punctuation — the comparison is exact. </Accordion> <Accordion title="A downstream node never runs"> Check that the downstream node appears as the `target` of at least one edge whose `source` actually executes. A node with no incoming edge and no entry in `entry_points` will never fire. </Accordion> </AccordionGroup> ## Next Steps * [Tagging Graph Workflow Edges with Metadata](/docs/examples/examples/graph-workflow-metadata) — production patterns for routing hints, telemetry tags, and audit labels * [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) — a fan-out/fan-in SDR enrichment DAG using the dict form end to end * [Graph Workflow Example](/docs/examples/examples/graph-workflow) — additional DAG shapes including localization and code review # Tagging Graph Workflow Edges with Metadata Source: https://docs.swarms.ai/docs/examples/examples/graph-workflow-metadata Attach severity, priority, and routing metadata to graph edges in a content moderation DAG — production observability for any DAG where ops needs to filter, group, or audit per-edge behavior. ## What This Example Shows * A real production use case: a content moderation graph where edges carry severity and priority tags * The shape of edge `metadata` in the Graph Workflow request payload * How to encode severity (`low`/`medium`/`high`/`critical`), routing target, and audit labels at the edge level * Why the API doesn't echo metadata back in the response, and how to correlate it client-side so downstream systems can still read it * Concrete ops patterns — log filters, SLO grouping, audit queries — that the metadata enables <Warning> The Graph Workflow endpoint (`POST /v1/graph-workflow/completions`) is a premium-only feature available on Pro, Ultra, and Premium plans. Free-tier keys receive a 403. [Upgrade your account](https://swarms.world/platform/account) to run production DAGs. </Warning> ## Why This Matters Content moderation is a routing problem masquerading as a classification problem. A post comes in, a classifier labels it, and the label has to get to the right place — `critical` to on-call humans inside an SLA, `medium` to a review queue, `low` to passive logging — each with different retry policies, audit requirements, and downstream tooling. When this routing logic lives inside agent prompts, it's invisible to ops; when it lives in glue code, it's not auditable. Edge metadata moves the routing semantics to where they belong: the edges of the DAG. Once ops can read `severity: "critical"` straight off the edge, dashboards group correctly, audit queries become one-liners, and the agents stay focused on the classification job. This tutorial shows the pattern in a content moderation DAG and then shows how downstream systems consume that metadata by correlating it, client-side, against the response. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } ``` ## Step 2: Sketch the Moderation DAG A single classifier fans out to three downstream routes, each handling a different severity tier. Each edge carries the routing semantics ops cares about. ```text theme={null} ┌── severity:critical ──> [HumanEscalation] [ContentClassifier] ──────────┼── severity:medium ────> [ReviewQueueRouter] └── severity:low ───────> [PassiveLogger] ``` Three edges, three different metadata blocks. The classifier itself is metadata-agnostic — it just labels and writes; the metadata on the edges tells the platform and downstream tools how each label should be handled. ## Step 3: Define the Agents ```python theme={null} agents = [ { "agent_name": "ContentClassifier", "description": "Classifies user-generated content by moderation severity.", "system_prompt": ( "You are a content moderation classifier. Read the user-generated " "content and emit a JSON object with these fields:\n" " severity: 'critical' | 'high' | 'medium' | 'low'\n" " categories: array of {hate, harassment, self_harm, csam, spam, " "spam_link, sexual_minor, violence, none}\n" " confidence: float between 0 and 1\n" " rationale: one sentence explaining the classification\n" "Return ONLY the JSON object." ), "model_name": "gpt-4.1", "max_tokens": 2000, "temperature": 0.1, "max_loops": 1, }, { "agent_name": "HumanEscalation", "description": "Drafts an escalation packet for an on-call human reviewer.", "system_prompt": ( "You receive a content moderation classification with a 'critical' " "severity label. Draft a 4-bullet escalation packet for an on-call " "human reviewer: (1) the content fragment, (2) the rationale, " "(3) the category, (4) recommended immediate action. Be terse — " "this lands on a pager." ), "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "ReviewQueueRouter", "description": "Formats a medium-severity item for the asynchronous review queue.", "system_prompt": ( "You receive a moderation classification with 'medium' or 'high' " "severity. Produce a JSON object suitable for the review queue: " "{queue: 'standard'|'priority', sla_hours: int, tags: [..], " "summary: string}. Return ONLY the JSON object." ), "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "PassiveLogger", "description": "Emits a compact analytics record for low-severity content.", "system_prompt": ( "You receive a 'low' severity classification. Produce a single-line " "JSON record with: {ts_unix, category, rationale_short}. No prose, " "JSON only." ), "model_name": "gpt-4.1", "max_tokens": 600, "temperature": 0.1, "max_loops": 1, }, ] ``` ## Step 4: Attach Severity and Routing Metadata to Edges This is the load-bearing step. Each edge from the classifier into a downstream route gets a `metadata` block that encodes severity, priority, target queue, SLA budget, and audit label. The keys you pick become the keys your dashboards and audit scripts filter on, so standardize them across your team. ```python theme={null} edges = [ { "source": "ContentClassifier", "target": "HumanEscalation", "metadata": { "severity": "critical", "priority": "p0", "route": "on_call_human", "sla_minutes": 15, "retry_on_failure": True, "audit_tag": "trust_and_safety", "cost_center": "ts_critical", }, }, { "source": "ContentClassifier", "target": "ReviewQueueRouter", "metadata": { "severity": "medium", "priority": "p2", "route": "review_queue", "sla_hours": 24, "retry_on_failure": True, "audit_tag": "trust_and_safety", "cost_center": "ts_standard", }, }, { "source": "ContentClassifier", "target": "PassiveLogger", "metadata": { "severity": "low", "priority": "p4", "route": "analytics_sink", "sla_hours": 168, "retry_on_failure": False, "audit_tag": "analytics", "cost_center": "ts_passive", }, }, ] ``` <Note> Three edges from the same source, each with different metadata, is the canonical pattern for moderation routing. The classifier doesn't need to know about severity routing — every downstream node receives its label and the platform knows which edge it crossed and what tags that edge carried. </Note> The standard metadata fields production moderation teams converge on: | Field | Type | What it's for | | --------------------------- | ------------------------------------------- | ----------------------------------------------------------------------- | | `severity` | `"critical" \| "high" \| "medium" \| "low"` | The primary classification label, mirrored to the edge for filtering | | `priority` | `"p0" \| "p1" \| "p2" \| ...` | SLO grouping in dashboards | | `route` | string | Logical destination — `on_call_human`, `review_queue`, `analytics_sink` | | `sla_minutes` / `sla_hours` | integer | Per-edge SLA budget surfaced in alerting | | `retry_on_failure` | boolean | Operational signal that this edge crosses an external boundary | | `audit_tag` | string | Regulatory/compliance label — `"trust_and_safety"`, `"pii"`, `"sox"` | | `cost_center` | string | Billing attribution for chargeback across teams | ## Step 5: Submit the Workflow ```python theme={null} workflow_input = { "name": "Content-Moderation-Routing", "description": ( "Classifier fans out to three severity-routed handlers, with edge " "metadata carrying routing, SLA, and audit context." ), "agents": agents, "edges": edges, "entry_points": ["ContentClassifier"], "end_points": ["HumanEscalation", "ReviewQueueRouter", "PassiveLogger"], "max_loops": 1, "task": ( "Classify the following user-generated content and route it to the " "appropriate downstream handler: 'Hey @user just shared the address " "of that scammer — link in bio.'" ), "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() result = response.json() ``` ## Step 6: How the Metadata Flows Through the Response The `/v1/graph-workflow/completions` response (`outputs` keyed by `agent_name`, plus a flat `usage` object) does not echo edge metadata back to you — the API only returns per-node outputs and aggregate token usage, not a per-edge breakdown. The correlation has to happen client-side: since you already have the `edges` list you submitted, build a local index from it and join that against the `outputs` you get back. A downstream system reading the response typically does this: ```python theme={null} # 1. Persist the per-edge metadata alongside each downstream node's output # so your moderation pipeline can later answer "which edge produced this # escalation packet?" without re-running the graph. edge_index = {(e["source"], e["target"]): e.get("metadata", {}) for e in edges} outputs = result.get("outputs", {}) for downstream in ["HumanEscalation", "ReviewQueueRouter", "PassiveLogger"]: out = outputs.get(downstream) if not out: continue meta = edge_index.get(("ContentClassifier", downstream), {}) record = { "node": downstream, "severity": meta.get("severity"), "priority": meta.get("priority"), "route": meta.get("route"), "sla_minutes": meta.get("sla_minutes"), "sla_hours": meta.get("sla_hours"), "audit_tag": meta.get("audit_tag"), "cost_center": meta.get("cost_center"), "output_preview": str(out)[:300], } print(json.dumps(record, indent=2)) # 2. The `usage` object is a workflow-level total, not broken down per edge # or per cost_center — if you need per-cost-center attribution, divide it # up yourself (e.g. proportionally by node) using the cost_center tags in # your local edge_index. usage = result.get("usage", {}) print(f"\nTotal token cost: ${usage.get('token_cost', 0):.4f}") print(f"Cost per agent: ${usage.get('cost_per_agent', 0):.4f}") ``` <Info> The API doesn't return edge metadata in the response — you correlate against the same `edges` list you already built and submitted (as `edge_index` does above). Treat the metadata block as a forward contract between your request payload and your moderation infrastructure, not as something the platform hands back to you. </Info> ## Step 7: Critical-Severity Escalation — Read the Tagged Output For the on-call path specifically, you want to fast-path the metadata-tagged record into your pager: ```python theme={null} critical_meta = edge_index.get(("ContentClassifier", "HumanEscalation"), {}) if outputs.get("HumanEscalation") and critical_meta.get("severity") == "critical": pager_payload = { "service": critical_meta.get("audit_tag", "trust_and_safety"), "severity": critical_meta.get("severity"), "priority": critical_meta.get("priority"), "sla_minutes": critical_meta.get("sla_minutes"), "summary": str(outputs["HumanEscalation"])[:500], "source_job_id": result.get("job_id"), } # send_to_pagerduty(pager_payload) print("\nPAGER PAYLOAD:") print(json.dumps(pager_payload, indent=2)) ``` The on-call human gets the severity, the SLA budget, and a job ID they can replay if they need to see the full graph context — all from fields that originated on a single edge. ## How Ops Teams Actually Use This Three concrete patterns once metadata is on every edge: **Pattern 1 — Audit grep.** Compliance asks "show me every moderation decision tagged `trust_and_safety` in the last 7 days." With `audit_tag` on the edges that cross the regulated boundary, this becomes a one-line log query rather than a substring search across prompts. **Pattern 2 — SLO grouping.** Dashboards group p95 latency by `priority` (`p0`, `p2`, `p4`). You instantly see which on-call paths are missing their 15-minute SLA and which `p4` paths can absorb slowdowns without paging anyone. **Pattern 3 — Retry budget enforcement.** Edges tagged `retry_on_failure: true` are the ones that should be retried. When the retry budget for the day is consumed, you can selectively disable retries on `priority: "p4"` edges while keeping them on `p0` ones — a one-line config change rather than a code deploy. ## When Downstream Agents Should Inspect Upstream Metadata The standard case is the one above: metadata is for ops and downstream systems, not the agent. There is one situation where the agent itself should read it: when a single downstream node receives edges from heterogeneous upstreams and needs to branch on which one fired. For that case, include the metadata in the prompt template you assemble before submission: ```python theme={null} def build_synthesis_prompt(upstream_outputs: dict, edges: list, target: str) -> str: sections = [] for edge in edges: if edge["target"] != target: continue source = edge["source"] meta = edge.get("metadata", {}) section = f"## Upstream: {source}\n" if "severity" in meta: section += f"_Severity: {meta['severity']}_\n" if "audit_tag" in meta: section += f"_Audit tag: {meta['audit_tag']}_\n" section += "\n" + str(upstream_outputs.get(source, "")) sections.append(section) return "\n\n---\n\n".join(sections) ``` Most production DAGs do not need this — they get more mileage from the dashboard side of metadata than the prompt side. ## Putting It All Together ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} agents = [ { "agent_name": "ContentClassifier", "description": "Classifies user-generated content by moderation severity.", "system_prompt": "You are a content moderation classifier. Emit a JSON object with severity, categories, confidence, rationale. JSON only.", "model_name": "gpt-4.1", "max_tokens": 2000, "temperature": 0.1, "max_loops": 1, }, { "agent_name": "HumanEscalation", "description": "Drafts an escalation packet for on-call humans.", "system_prompt": "Draft a terse 4-bullet escalation packet for on-call review.", "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "ReviewQueueRouter", "description": "Routes medium-severity items to the async review queue.", "system_prompt": "Produce a JSON record for the review queue. JSON only.", "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "PassiveLogger", "description": "Logs low-severity content for analytics.", "system_prompt": "Produce a one-line JSON analytics record. JSON only.", "model_name": "gpt-4.1", "max_tokens": 600, "temperature": 0.1, "max_loops": 1, }, ] edges = [ { "source": "ContentClassifier", "target": "HumanEscalation", "metadata": { "severity": "critical", "priority": "p0", "route": "on_call_human", "sla_minutes": 15, "retry_on_failure": True, "audit_tag": "trust_and_safety", "cost_center": "ts_critical", }, }, { "source": "ContentClassifier", "target": "ReviewQueueRouter", "metadata": { "severity": "medium", "priority": "p2", "route": "review_queue", "sla_hours": 24, "retry_on_failure": True, "audit_tag": "trust_and_safety", "cost_center": "ts_standard", }, }, { "source": "ContentClassifier", "target": "PassiveLogger", "metadata": { "severity": "low", "priority": "p4", "route": "analytics_sink", "sla_hours": 168, "retry_on_failure": False, "audit_tag": "analytics", "cost_center": "ts_passive", }, }, ] workflow_input = { "name": "Content-Moderation-Routing", "description": "Classifier fans out to three severity-routed handlers.", "agents": agents, "edges": edges, "entry_points": ["ContentClassifier"], "end_points": ["HumanEscalation", "ReviewQueueRouter", "PassiveLogger"], "max_loops": 1, "task": ( "Classify and route: 'Hey @user just shared the address of that " "scammer — link in bio.'" ), "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) if response.status_code == 200: result = response.json() edge_index = {(e["source"], e["target"]): e.get("metadata", {}) for e in edges} print(f"Job ID: {result.get('job_id')}") print(f"Status: {result.get('status')}") outputs = result.get("outputs", {}) for downstream in ["HumanEscalation", "ReviewQueueRouter", "PassiveLogger"]: meta = edge_index.get(("ContentClassifier", downstream), {}) if downstream in outputs: print(f"\n[{downstream}] severity={meta.get('severity')} " f"priority={meta.get('priority')}") print(str(outputs[downstream])[:300]) else: print(f"Error: {response.status_code}") print(response.text) ``` ## Next Steps * [Graph Workflow Edge Formats Reference](/docs/examples/examples/graph-workflow-edge-formats) — the supported edge syntaxes side by side * [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) — fan-out/fan-in SDR enrichment DAG with retries and conditional paths * [Graph Workflow Example](/docs/examples/examples/graph-workflow) — additional DAG shapes including localization and code review # Graph Workflows for Production Pipelines Source: https://docs.swarms.ai/docs/examples/examples/graph-workflows-production Build production fan-out/fan-in DAGs with parallel branches that converge into a synthesis node. SDR enrichment pipeline with three parallel research agents, a synthesis agent, and a scoring agent. ## What This Example Shows * A real production DAG: an SDR (sales development) enrichment pipeline with three parallel research branches that converge into synthesis and scoring nodes * How to express fan-out → fan-in graphs with `edges`, `entry_points`, and `end_points` * Why this beats stacking `SequentialWorkflow` + `ConcurrentWorkflow` (single round-trip, server-side concurrency, single billing event) * How to read per-node outputs from the response so you can persist branch outputs to your CRM * Patterns for retries and conditional paths via downstream gating <Warning> The Graph Workflow endpoint (`POST /v1/graph-workflow/completions`) is a **premium-only** feature available on Pro, Ultra, and Premium plans. Free tier keys receive a 403. [Upgrade your account](https://swarms.world/platform/account) to run production DAGs on the Swarms API. </Warning> ## Why This Matters Sales teams burn the first 20 minutes of every cold outreach reading three different tabs — LinkedIn for the buyer, Crunchbase for the company, and a news search for the trigger event. Then somebody distills it into a one-line pitch hook, somebody else scores the lead, and only then does the SDR send. That sequence is a DAG, not a chain: the three lookups are independent of each other, but they all block the synthesis step, which blocks the scoring step. A Graph Workflow lets you describe that DAG once and have the platform run the three lookups in parallel, fan them into the synthesis node, then feed scoring — in a single API call with one billing event. You stop maintaining glue code that orchestrates async tasks, and your SDR pipeline runs 3-5x faster than the sequential version. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } ``` ## Step 2: Sketch the Graph Before You Code It The graph for an SDR enrichment looks like this: ```text theme={null} [BuyerResearcher] ──┐ [CompanyResearcher] ──┼──> [PitchSynthesizer] ──> [LeadScorer] [TriggerResearcher] ──┘ ``` Three independent researchers (parallel) → synthesizer (waits for all three) → scorer (waits for synthesis). Three edges into the synthesizer, one edge out to the scorer. <Note> Always draw the graph on paper before encoding it. The edges and `entry_points`/`end_points` fields are mechanical once the picture is right — and almost always wrong when they aren't. </Note> ## Step 3: Define the Agents Each node is a specialist. Researchers are tuned low-temperature for factual recall; the synthesizer runs slightly warmer to write copy; the scorer is the coldest of all because we want a deterministic verdict. ```python theme={null} agents = [ { "agent_name": "BuyerResearcher", "description": "Researches the individual buyer and their role.", "system_prompt": ( "You are a sales researcher specializing in buyer personas. Given a " "name, title, and company, produce: (1) role responsibilities, " "(2) likely KPIs, (3) recent public statements or content, " "(4) seniority and likely budget authority. Be concise." ), "model_name": "gpt-4.1", "max_tokens": 3000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "CompanyResearcher", "description": "Researches the target company.", "system_prompt": ( "You are a company research analyst. Given a company name, produce: " "(1) what they do in one sentence, (2) headcount and stage, " "(3) likely tech stack, (4) recent funding or M&A. Be concise." ), "model_name": "gpt-4.1", "max_tokens": 3000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "TriggerResearcher", "description": "Finds a recent trigger event worth referencing.", "system_prompt": ( "You are a trigger-event researcher. Given a company, find ONE " "recent (last 60 days) public event that creates a natural opening " "for outbound: a hire, a launch, a layoff, a funding round, a " "press release. Output a single trigger with date and source." ), "model_name": "gpt-4.1", "max_tokens": 2000, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "PitchSynthesizer", "description": "Synthesizes buyer + company + trigger into a 1-line hook.", "system_prompt": ( "You are a senior SDR. Given buyer research, company research, and " "a trigger event, write a single outbound opener of at most 35 " "words that (a) references the trigger, (b) connects it to a KPI " "the buyer owns, (c) ends with a clear question. No fluff, no " "'hope you're doing well.'" ), "model_name": "gpt-4.1", "max_tokens": 1500, "temperature": 0.5, "max_loops": 1, }, { "agent_name": "LeadScorer", "description": "Scores the lead 1-100 with a confidence band.", "system_prompt": ( "You are a revenue operations analyst. Given the buyer profile, " "the company profile, the trigger event, and the synthesized " "pitch, return a JSON object with fields: score (1-100), " "confidence ('low'|'medium'|'high'), tier ('A'|'B'|'C'), and " "one_line_rationale. Return ONLY the JSON object." ), "model_name": "gpt-4.1", "max_tokens": 800, "temperature": 0.1, "max_loops": 1, }, ] ``` ## Step 4: Wire the Edges Three fan-in edges, one straight edge. The `entry_points` are the three researchers (no upstream dependencies); the `end_point` is the scorer (no downstream dependencies). ```python theme={null} edges = [ {"source": "BuyerResearcher", "target": "PitchSynthesizer"}, {"source": "CompanyResearcher", "target": "PitchSynthesizer"}, {"source": "TriggerResearcher", "target": "PitchSynthesizer"}, {"source": "PitchSynthesizer", "target": "LeadScorer"}, ] ``` ## Step 5: Submit the Workflow ```python theme={null} LEAD = { "buyer_name": "Jamie Chen", "buyer_title": "VP of Engineering", "company": "Northwind Analytics", } task = ( f"Lead: {LEAD['buyer_name']}, {LEAD['buyer_title']} at {LEAD['company']}. " "Run the full enrichment pipeline: buyer research, company research, " "trigger event search, pitch synthesis, and final lead scoring." ) workflow_input = { "name": "SDR-Enrichment-Pipeline", "description": ( "Fan-out enrichment DAG. Three researchers run in parallel, converge " "into a pitch synthesizer, then feed a lead scorer." ), "agents": agents, "edges": edges, "entry_points": ["BuyerResearcher", "CompanyResearcher", "TriggerResearcher"], "end_points": ["LeadScorer"], "max_loops": 1, "task": task, "auto_compile": True, "verbose": False, } response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=workflow_input, timeout=300, ) response.raise_for_status() result = response.json() ``` ## Step 6: Read the Per-Node Output Every node's output is keyed by `agent_name` under `outputs`. Persist them individually — the buyer profile belongs on the contact record, the company profile on the account record, the pitch in the sequencer, the score in the CRM lead-scoring column. ```python theme={null} outputs = result.get("outputs", {}) stages = [ ("PARALLEL RESEARCH", ["BuyerResearcher", "CompanyResearcher", "TriggerResearcher"]), ("SYNTHESIS", ["PitchSynthesizer"]), ("SCORING", ["LeadScorer"]), ] for stage_label, names in stages: print(f"\n{'=' * 60}\n{stage_label}\n{'=' * 60}") for name in names: out = outputs.get(name, "") if isinstance(out, list): out = "\n".join(str(x) for x in out) print(f"\n[{name}]\n{str(out)[:400]}") # The scorer returned JSON — parse it import re score_raw = outputs.get("LeadScorer", "") if isinstance(score_raw, list): score_raw = " ".join(str(x) for x in score_raw) match = re.search(r"\{.*\}", str(score_raw), re.DOTALL) if match: lead_score = json.loads(match.group(0)) print(f"\nFinal score: {lead_score['score']} ({lead_score['tier']}-tier, " f"{lead_score['confidence']} confidence)") usage = result.get("usage", {}) print(f"\nTotal cost: ${usage.get('token_cost', 0):.4f}") ``` ## Why This Beats Sequential + Concurrent Stacking You could build the same pipeline by calling `ConcurrentWorkflow` for the three researchers, manually stitching their outputs into a prompt, then calling `SequentialWorkflow` for synthesis → scoring. That works. It's also worse: | Concern | Sequential + Concurrent (DIY) | Graph Workflow | | ----------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | API calls | 2 (concurrent, then sequential) | **1** | | Billing events | 2 separate cost records | **1 unified record** | | Glue code you maintain | "wait for all 3, then build prompt, then call next workflow" | **None** — declared in `edges` | | Server-side parallelism | Yes for first hop only | **Yes across the whole DAG** | | Wall clock | Sum of (slowest researcher + synth + scorer) plus 2 round-trips | **Slowest researcher + synth + scorer**, single round-trip | | Failure handling | You retry whichever hop failed | A node failure raises an error for the whole request — retry the request, or budget extra `max_loops` on flaky nodes (see below) | | Auditability | Two job IDs in your logs | **One `job_id` you can replay** | ## Adding Conditional Paths and Retries Two production patterns to layer on top: **Conditional gating (early exit on cold leads).** Add a `Qualifier` node before the heavy research and let the synthesizer's prompt instruct it to output "SKIP" if the lead score's company profile fails a hard filter (e.g., \< 50 employees, US-only). Downstream nodes still run, but their prompts can be written to no-op when they see "SKIP" upstream. **Retries on a flaky node.** `auto_compile: true` pre-validates the graph (auto-setting entry/end points, checking structure) and caches the compiled execution plan — it does not retry failed nodes. If any node raises an unhandled exception, the whole `/v1/graph-workflow/completions` request fails and the caller needs to retry the request. What you *can* do per-node is raise that agent's own `max_loops`, which gives it more internal iterations to recover from a bad tool call or malformed output within its own run before handing off to downstream nodes — that's agent-level resilience, not graph-level, automatic retry-on-failure. ```python theme={null} agents[2]["max_loops"] = 2 # TriggerResearcher gets extra internal iterations ``` ## Scaling the Pattern Drop in any production DAG by swapping the node prompts: | Pipeline | Entry points (parallel) | Middle | End point | | --------------------- | ---------------------------- | ------------------ | -------------- | | **SDR enrichment** | Buyer / Company / Trigger | Pitch Synth | Lead Scorer | | **Underwriting** | Credit / Income / Collateral | Risk Synth | Approver | | **Incident response** | Logs / Metrics / Alerts | Root-Cause Synth | Runbook Picker | | **CI/CD code review** | Lint / Security / Perf | Review Synth | Merge Gate | | **Clinical triage** | History / Vitals / Imaging | Differential Synth | Disposition | Everything else — request shape, response shape, billing, retries — stays identical. ## Cost vs. Building It Yourself Concrete numbers from a real SDR team enriching 1,000 leads per week: | Approach | Time per lead | Cost per lead | Engineering owned | | ------------------------------------------------------------------------ | ------------- | ------------------------------------ | ------------------------------------ | | Manual SDR research (LinkedIn + Crunchbase + news) | 18-25 min | \~\$22 in SDR time | None | | Custom async orchestration in-house (Lambda + Step Functions + LLM glue) | \~6-8 sec | \~\$0.03 in API + \~\$0.005 in infra | 2 engineers, \~\$300k/yr to maintain | | **Graph Workflow endpoint** | **\~3-5 sec** | **\~\$0.02-\$0.04 in API** | **None — declared in JSON** | Math: 1,000 leads/week at \$22 manual vs. ~~\$0.03 on the endpoint is **\$22,000/week saved** (~~\$1.1M/year), before counting the engineering team you don't need to staff for the DIY path. The pipeline goes live in a day instead of a quarter. <Warning> Per-lead cost will vary with model choice and token volume — `gpt-4.1` on five short nodes is the cheap path; swap to `anthropic/claude-opus-4-8` if your synthesizer needs deeper reasoning. </Warning> ## Next Steps * [Reasoning Agents for Hard Analytical Problems](/docs/examples/examples/reasoning-agents-tutorial) — when one node in your DAG needs deliberation instead of recall * [Graph Workflow Example](/docs/examples/examples/graph-workflow) — additional DAG shapes (content localization, due diligence, code review) # Group Chat Example Source: https://docs.swarms.ai/docs/examples/examples/group-chat Build a product strategy brainstorm with GroupChat ## Product Strategy Brainstorm This example demonstrates how to facilitate a collaborative discussion between multiple specialist agents using GroupChat - perfect for brainstorming, cross-functional planning, and multi-perspective problem solving. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define the Discussion Panel Create agents with distinct expertise who will collaborate through group conversation: ```python theme={null} def run_product_brainstorm(product_brief: str) -> dict: """Run a collaborative product strategy discussion.""" swarm_config = { "name": "Product Strategy GroupChat", "description": "Cross-functional product brainstorm", "swarm_type": "GroupChat", "task": f"""Collaborate on a go-to-market strategy for the following product: {product_brief} Each participant should contribute their domain expertise, build on others' ideas, and identify blind spots. Converge on a concrete action plan.""", "agents": [ { "agent_name": "Product Manager", "description": "Drives product vision, roadmap, and prioritization", "system_prompt": """You are a Senior Product Manager. In this group discussion: - Define the core value proposition and target personas - Prioritize features for the launch MVP - Identify key metrics and success criteria - Challenge assumptions and ask clarifying questions Be concise and action-oriented. Build on what other participants say.""", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Growth Marketer", "description": "Designs acquisition channels and launch campaigns", "system_prompt": """You are a Growth Marketing Lead. In this group discussion: - Propose acquisition channels ranked by expected ROI - Design the launch campaign strategy - Suggest pricing and positioning tactics - Estimate CAC benchmarks for each channel Be data-driven and specific with numbers. React to others' suggestions.""", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Engineering Lead", "description": "Assesses technical feasibility and delivery timelines", "system_prompt": """You are an Engineering Lead. In this group discussion: - Evaluate technical feasibility of proposed features - Flag complexity risks and dependencies - Propose a realistic MVP scope and timeline - Suggest technical shortcuts for faster time-to-market Be pragmatic. Push back on scope creep and offer alternatives.""", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Customer Success Lead", "description": "Represents the customer voice and retention strategy", "system_prompt": """You are a Customer Success Lead. In this group discussion: - Advocate for the end-user experience - Identify onboarding friction points - Propose retention and engagement hooks - Share common objections and how to address them Ground the discussion in real customer needs. Challenge ideas that overlook usability.""", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "temperature": 0.5 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 3: Run the Brainstorm ```python theme={null} # Product brief brief = """ PRODUCT: TaskPilot - AI-powered project management tool for remote teams TARGET: Small-to-mid engineering teams (5-30 people) KEY FEATURES: - AI auto-assigns tasks based on team capacity and skill matching - Natural language standup summaries generated from activity - Smart sprint planning that predicts delivery risk - Integrations with GitHub, Slack, and Jira STAGE: Pre-launch, MVP built, 12 beta users BUDGET: $50K for initial go-to-market TIMELINE: 8 weeks to public launch """ # Run brainstorm result = run_product_brainstorm(brief) # Display the group discussion for output in result.get("output", []): participant = output["role"] content = output["content"] print(f"\n{'='*50}") print(f"{participant.upper()}") print(f"{'='*50}") print(content[:800] + "...") ``` **Expected Output:** ``` ================================================== PRODUCT MANAGER ================================================== Based on the brief, here's my take on the launch strategy: VALUE PROPOSITION: "Stop managing tasks. Let AI manage them for you." Target persona: Engineering managers at remote-first startups (5-30 devs) who currently use Jira/Linear but struggle with sprint planning accuracy. MVP PRIORITY (Must-have for launch): 1. AI task assignment - this is the core differentiator 2. Slack integration - lowest friction adoption path 3. Standup summaries - immediate daily value DEFER post-launch: - Jira migration (complex, slow ROI) - Delivery risk prediction (needs more data) SUCCESS METRICS: - 50 teams onboarded in 8 weeks - 60% WAU after first month - NPS > 40 from beta cohort... ================================================== GROWTH MARKETER ================================================== Love the positioning. Here's my channel strategy for the $50K budget: CHANNEL ALLOCATION: 1. Product Hunt launch ($2K) - Expected: 500-1K signups, best ROI 2. Dev-focused content marketing ($15K) - Blog posts, Twitter threads 3. Slack community partnerships ($8K) - Sponsor remote-work communities 4. LinkedIn ads targeting eng managers ($15K) - Est. CAC: $35-50 5. Beta user referral program ($10K) - Give existing 12 users incentives PRICING: - Free tier: up to 5 users (growth loop) - Pro: $12/user/month (target ACV ~$2,500) - Launch discount: 40% off annual for first 3 months... ================================================== ENGINEERING LEAD ================================================== A few reality checks on the proposed scope: FEASIBLE IN 8 WEEKS: - AI task assignment: Core algo exists from MVP, needs polish. 3 weeks. - Slack integration: Standard OAuth + webhooks. 2 weeks. - Standup summaries: We can ship a v1 using activity logs. 1 week. RISKS: - GitHub integration adds 2-3 weeks if we want bidirectional sync. Recommend: start with read-only GitHub status sync (1 week). - AI assignment accuracy depends on historical data. New teams will have a cold-start problem. Suggest: manual override + learning mode. TIMELINE: 6 weeks eng + 2 weeks buffer = doable if we freeze scope NOW... ================================================== CUSTOMER SUCCESS LEAD ================================================== From our 12 beta users, here's what I'm seeing: TOP ONBOARDING FRICTION: 1. Teams don't trust AI assignments on day one - need a "suggestion mode" before fully autonomous mode 2. Connecting Slack takes 3 clicks but users expect 1-click setup 3. No clear "aha moment" in first 5 minutes RETENTION HOOKS I'd prioritize: - Daily standup digest in Slack (passive value, no effort needed) - Weekly "time saved" report (quantifies ROI for the buyer) - Team leaderboard for sprint completion (engagement driver) COMMON OBJECTION: "How is this different from Jira automation rules?" Answer: We need a clear comparison page and a 2-minute demo video... ``` <Note> GroupChat enables collaborative discussion where agents can build on each other's ideas. Use it when you need cross-functional input on the same problem - each agent contributes their domain expertise while reacting to the broader conversation context. </Note> # Heavy Swarm Example Source: https://docs.swarms.ai/docs/examples/examples/heavy-swarm Run deep multi-perspective research and analysis with HeavySwarm ## Comprehensive Market Intelligence with HeavySwarm This example demonstrates how to use HeavySwarm for deep, multi-perspective analysis. Unlike other swarm types, HeavySwarm automatically creates and manages five specialized agents (Research, Analysis, Alternatives, Verification, Synthesis) — you provide the task, configuration, and an empty `agents` array. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import json import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define the Research Function HeavySwarm creates its own five specialized agents internally — pass an empty `agents` array and configure the swarm using HeavySwarm-specific parameters: ```python theme={null} def run_heavy_analysis(task: str, heavy_swarm_max_loops: int = 1, max_loops: int = 1) -> dict: """Run a deep multi-perspective analysis using HeavySwarm.""" swarm_config = { "name": "Market Intelligence Swarm", "description": "Deep multi-agent research and analysis", "swarm_type": "HeavySwarm", "task": task, "agents": [], "heavy_swarm_max_loops": heavy_swarm_max_loops, "heavy_swarm_question_agent_model_name": "gpt-4.1", "heavy_swarm_worker_model_name": "claude-sonnet-4-20250514", "max_loops": max_loops } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=300 ) return response.json() ``` ### Step 4: Run the Analysis ```python theme={null} # Define a complex research task task = """ Analyze the competitive landscape of the AI infrastructure market in 2025. Focus on: cloud GPU providers, inference optimization startups, open-source model serving frameworks, and edge AI deployment platforms. Evaluate market sizing, key players, moats, and identify the most promising investment opportunities with risk-adjusted return potential. """ # Run HeavySwarm analysis result = run_heavy_analysis(task) # Display results from each specialized agent for output in result.get("output", []): agent = output["role"] content = output["content"] print(f"\n{'='*60}") print(f"{agent}") print(f"{'='*60}") # Handle content that may be a dict (question generator) or string if isinstance(content, dict): for key, value in content.items(): if key != "thinking": print(f"\n{key}:") print(f" {value}") else: print(str(content)[:800] + "...") ``` **Expected Output:** ``` ============================================================ Question Generator Agent ============================================================ research_question: What are the current market sizes, growth rates, and key players across cloud GPU, inference optimization, model serving, and edge AI segments? analysis_question: What statistical patterns emerge from funding rounds, revenue multiples, and customer adoption rates across AI infrastructure subsectors? alternatives_question: What are the highest risk-adjusted investment strategies considering direct equity, infrastructure ETFs, and picks-and-shovels approaches across these segments? verification_question: How do reported market projections and competitive moat claims align with verified deployment data, customer churn rates, and technical benchmarks? ============================================================ Research-Agent ============================================================ ## AI Infrastructure Market Research ### Market Overview The global AI infrastructure market reached approximately $65B in 2024 and is projected to exceed $120B by 2027 (38% CAGR). ### Cloud GPU Providers Key players: NVIDIA (dominant), AMD (growing share), AWS Trainium/Inferentia (custom silicon), Google TPU, CoreWeave (GPU-as-a-service) Market dynamics: Severe GPU shortage easing in 2025, but demand continues to outpace supply for H100/B200 clusters... ============================================================ Analysis-Agent ============================================================ ## Statistical Analysis of AI Infrastructure Trends ### Funding Pattern Analysis - Total VC funding in AI infra: $18.2B in 2024 (up 142% from 2023) - Median Series B valuation: 45x ARR for inference optimization startups - Customer acquisition efficiency: Cloud GPU providers show 0.8x CAC/LTV ratio vs 1.2x for edge AI platforms ### Adoption Rate Analysis - Enterprise GPU cloud adoption: 67% of Fortune 500 (up from 34% in 2023) - Open-source model serving: vLLM and TensorRT-LLM dominating with 78% combined market share in inference workloads... ============================================================ Alternatives-Agent ============================================================ ## Investment Strategy Alternatives ### Strategy 1: Infrastructure Picks-and-Shovels (Recommended) Focus: NVIDIA, networking (Arista, Broadcom), power/cooling Risk: Moderate | Expected Return: 25-35% annualized Rationale: Benefits from all AI growth regardless of which models win ### Strategy 2: Pure-Play Inference Optimization Focus: Emerging startups (Groq, Cerebras, Together AI) Risk: High | Expected Return: 3-10x over 5 years (venture-style) Rationale: Inference costs are the primary bottleneck... ============================================================ Verification-Agent ============================================================ ## Verification Assessment ### Claim: AI infra market at $65B (2024) Status: VERIFIED Sources: Gartner ($62-68B range), IDC ($64.5B), cross-referenced with public company revenues (NVIDIA data center: $47.5B alone) ### Claim: 38% CAGR through 2027 Status: PARTIALLY VERIFIED Note: Estimates range from 28-45% depending on methodology. Conservative base case of 30% is better supported by deployment data... ============================================================ Synthesis Agent ============================================================ ## Executive Summary The AI infrastructure market represents a verified $65B opportunity growing at 30-38% CAGR. Our multi-agent analysis reveals strong consensus on three key findings: 1. **Infrastructure layer offers best risk-adjusted returns** - All four specialist agents converge on picks-and-shovels as the safest approach 2. **Inference optimization is the highest-growth subsector** - 142% YoY funding growth with verified demand signals 3. **Edge AI remains early-stage** - Higher risk but strategic importance for the 2026-2028 cycle... ``` ### Step 5: Multi-Loop Deep Dive (Optional) For tasks requiring deeper analysis, increase `heavy_swarm_max_loops` and `max_loops`. Each iteration builds on previous results: ```python theme={null} # Run a deeper 2-loop analysis for thorough due diligence deep_result = run_heavy_analysis( task="Conduct due diligence on CoreWeave as a potential investment. Evaluate their GPU cloud infrastructure business model, competitive positioning against AWS/Azure/GCP, financial health, customer concentration risk, and long-term defensibility.", heavy_swarm_max_loops=2, max_loops=2 ) # The synthesis agent output from the final loop contains the most refined analysis outputs = deep_result.get("output", []) for output in outputs: if output["role"] == "Synthesis Agent": print("FINAL SYNTHESIZED ANALYSIS:") print(str(output["content"])[:2000]) ``` <Note> HeavySwarm is best suited for complex research and analysis tasks that benefit from multiple specialized perspectives. It automatically decomposes your task into four targeted questions, executes them in parallel across Research, Analysis, Alternatives, and Verification agents, then synthesizes everything into a comprehensive report. No agent configuration is needed — just provide the task and an empty `agents` array. </Note> # Hierarchical Workflow Example Source: https://docs.swarms.ai/docs/examples/examples/hierarchical-workflow Build a software development team with HierarchicalSwarm ## Software Development Team with Hierarchical Coordination This example demonstrates how to build a development team where a tech lead coordinates specialized engineers - perfect for complex projects requiring oversight and synthesis. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define Your Hierarchical Team Create a development team of 5 specialist agents. HierarchicalSwarm supplies its own director agent to coordinate them, so every agent you list is a worker: ```python theme={null} def design_auth_system(requirements: str) -> dict: """Design an authentication system using a hierarchical development team.""" swarm_config = { "name": "Software Development Team", "description": "Hierarchical team with tech lead coordinating specialists", "swarm_type": "HierarchicalSwarm", "task": requirements, "agents": [ { "agent_name": "Tech Lead", "description": "Senior engineer coordinating the team", "system_prompt": "You are a tech lead. Review all work from your team, make architectural decisions, identify gaps, and synthesize everything into a cohesive technical plan. Provide final recommendations.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Backend Engineer", "description": "API and authentication specialist", "system_prompt": "You are a backend engineer specializing in authentication. Design: API endpoints, authentication flow, token management, and session handling. Be specific and technical.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Database Engineer", "description": "Database design expert", "system_prompt": "You are a database engineer. Design: user table schema, indexes, relationships, and data security measures. Consider scalability and performance.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Security Engineer", "description": "Application security specialist", "system_prompt": "You are a security engineer. Identify: security requirements, encryption standards, vulnerability risks, and mitigation strategies. Focus on authentication security.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "QA Engineer", "description": "Testing strategy expert", "system_prompt": "You are a QA engineer. Design: test strategy, test cases, edge cases, security tests, and performance tests for the authentication system.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=120 ) return response.json() ``` ### Step 4: Run the Team ```python theme={null} # Project requirements requirements = """ Design a user authentication system with these requirements: - OAuth2 + JWT tokens - Support email/password and social login - Two-factor authentication - Password reset flow - Session management - Handle 10,000 concurrent users """ # Run the hierarchical team result = design_auth_system(requirements) # Display results for output in result.get("output", []): print(f"\n{'='*60}") print(f"{output['role']}") print('='*60) # Handle content as string or list content = output['content'] if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:400] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` **Expected Output:** ``` ============================================================ Tech Lead ============================================================ After reviewing all team inputs, here's our unified authentication system design: **Architecture Decision:** OAuth2 with JWT access tokens (15min) and refresh tokens (7 days) **Database:** PostgreSQL with proper indexing on email/user_id **Security:** bcrypt (cost 12), rate limiting, 2FA via TOTP **API:** RESTful endpoints with /auth prefix **Testing:** 85% coverage target, load testing for 10k users [Detailed synthesis of all team inputs...] ============================================================ Backend Engineer ============================================================ API Endpoints: POST /auth/register - Create new user account POST /auth/login - Authenticate and issue tokens POST /auth/refresh - Refresh access token POST /auth/logout - Invalidate tokens GET /auth/verify - Verify token validity POST /auth/2fa/enable - Enable two-factor auth POST /auth/2fa/verify - Verify 2FA code ... ============================================================ Database Engineer ============================================================ Schema Design: users table: - id (UUID, primary key) - email (VARCHAR(255), unique index) - password_hash (VARCHAR(255)) - email_verified (BOOLEAN, default false) - created_at (TIMESTAMP) - updated_at (TIMESTAMP) Indexes: - idx_users_email (unique) - idx_users_created_at ... ============================================================ Security Engineer ============================================================ Security Requirements: HIGH PRIORITY: - Passwords: min 12 chars, require special characters - bcrypt hashing with cost factor 12 - Rate limiting: 5 failed attempts = 15min lockout - HTTPS only, no HTTP fallback - JWT stored in httpOnly cookies MEDIUM PRIORITY: - 2FA via TOTP (Google Authenticator) - Email verification required ... ============================================================ QA Engineer ============================================================ Testing Strategy: Unit Tests (60% coverage): - Password validation logic - Token generation/verification - Email validation - 2FA code generation Integration Tests (25% coverage): - Full login flow - Registration + verification - Password reset flow ... Total cost: $0.1132 Execution time: 42.5s ``` <Note> HierarchicalSwarm creates its own director agent (model set by `director_model_name`, default `gpt-5.4`) that plans the work, assigns it to the agents you supply, and synthesizes their outputs. Every agent in `agents` is a worker. </Note> # Hospital Medical Team Swarm Source: https://docs.swarms.ai/docs/examples/examples/hospital-team Learn how to create a hierarchical swarm that simulates a real medical team with a doctor leader coordinating nurses and assistants. ## What This Example Shows * Creating a hierarchical swarm with leader and worker agents * Coordinating multiple specialized medical professionals * Implementing role-based agent responsibilities * Managing complex multi-agent workflows ## Installation ```bash theme={null} pip3 install -U swarms-client ``` ## Get Your Swarms API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate a new API key 4. Store it securely in your environment variables ## Code ```python theme={null} import json import os from swarms_client import SwarmsClient from dotenv import load_dotenv # Load environment variables load_dotenv() # Initialize the client client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) def create_medical_unit_swarm(client, patient_info): """ Creates and runs a simulated medical unit swarm with a doctor (leader), nurses, and a medical assistant. """ return client.swarms.run( name="Hospital Medical Unit", description="A simulated hospital unit with a doctor (leader), nurses, and a medical assistant collaborating on patient care.", swarm_type="HierarchicalSwarm", task=patient_info, agents=[ { "agent_name": "Dr. Smith - Attending Physician", "description": "The lead doctor responsible for diagnosis, treatment planning, and team coordination.", "system_prompt": ( "You are Dr. Smith, the attending physician and leader of the medical unit. " "You review all information, make final decisions, and coordinate the team. " "Provide a diagnosis, recommend next steps, and delegate tasks to the nurses and assistant." ), "model_name": "gpt-4.1", "role": "leader", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, }, { "agent_name": "Nurse Alice", "description": "A registered nurse responsible for patient assessment, vital signs, and reporting findings to the doctor.", "system_prompt": ( "You are Nurse Alice, a registered nurse. " "Assess the patient's symptoms, record vital signs, and report your findings to Dr. Smith. " "Suggest any immediate nursing interventions if needed." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.5, }, { "agent_name": "Nurse Bob", "description": "A registered nurse assisting with patient care, medication administration, and monitoring.", "system_prompt": ( "You are Nurse Bob, a registered nurse. " "Assist with patient care, administer medications as ordered, and monitor the patient's response. " "Communicate any changes to Dr. Smith." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.5, }, { "agent_name": "Medical Assistant Jane", "description": "A medical assistant supporting the team with administrative tasks and basic patient care.", "system_prompt": ( "You are Medical Assistant Jane. " "Support the team by preparing the patient, collecting samples, and handling administrative tasks. " "Report any relevant observations to the nurses or Dr. Smith." ), "model_name": "claude-sonnet-4-20250514", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.5, }, ], ) # Example patient case patient_symptoms = """ Patient: 45-year-old female Chief Complaint: Chest pain and shortness of breath for 2 days Symptoms: - Sharp chest pain that worsens with deep breathing - Shortness of breath, especially when lying down - Mild fever (100.2°F) - Dry cough - Fatigue """ # Run the medical team swarm out = create_medical_unit_swarm(client, patient_symptoms) print(json.dumps(out, indent=4)) ``` ## Swarm Architecture Explained ### Agent Roles * **Leader Agent (Dr. Smith)**: Coordinates the team, makes final decisions * **Worker Agents (Nurses & Assistant)**: Execute specific tasks and report back ### Swarm Type: HierarchicalSwarm This swarm type creates a clear chain of command where: 1. The leader agent receives the initial task 2. Worker agents process their specialized areas 3. Results flow back to the leader for final synthesis 4. The leader provides the comprehensive final output ## Expected Output The swarm will provide a coordinated medical assessment including: * **Nurse Alice's Assessment**: Vital signs, immediate observations * **Nurse Bob's Care Plan**: Medication and monitoring recommendations * **Medical Assistant's Support**: Administrative and preparation tasks * **Dr. Smith's Final Diagnosis**: Comprehensive treatment plan and coordination ## Use Cases This pattern is ideal for: * **Medical Teams**: Coordinated patient care and diagnosis * **Legal Teams**: Multi-expert document review and analysis * **Research Teams**: Collaborative data analysis and interpretation * **Support Teams**: Coordinated customer issue resolution * **Development Teams**: Code review and quality assurance ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Customization Ideas Adapt this pattern for: * **Emergency Response**: Fire, police, and medical coordination * **Project Management**: Team leads coordinating specialists * **Quality Control**: Inspectors coordinating with technicians * **Customer Service**: Supervisors managing support agents ## Next Steps After mastering hierarchical swarms, explore: * Sequential workflows for step-by-step processes * Concurrent workflows for parallel execution * Majority voting for consensus-based decisions * Agent routing for dynamic task distribution # ICD-10 Medical Analysis Swarm Source: https://docs.swarms.ai/docs/examples/examples/icd-analysis Learn how to create a concurrent workflow swarm that analyzes medical conditions using multiple specialized agents working in parallel. ## What This Example Shows * Creating a concurrent workflow swarm for parallel analysis * Implementing multiple specialized medical analysis agents * Coordinating agents to work simultaneously for faster results * Comprehensive medical code interpretation and analysis ## Installation ```bash theme={null} pip3 install -U swarms-client ``` ## Get Your Swarms API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate a new API key 4. Store it securely in your environment variables ## Code ```python theme={null} import json import os from swarms_client import SwarmsClient from dotenv import load_dotenv # Load environment variables load_dotenv() # Initialize the client client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), ) # Example patient symptoms for analysis patient_symptoms = """ Patient: 45-year-old female Chief Complaint: Chest pain and shortness of breath for 2 days Symptoms: - Sharp chest pain that worsens with deep breathing - Shortness of breath, especially when lying down - Mild fever (100.2°F) - Dry cough - Fatigue """ # Create and run the ICD analysis swarm out = client.swarms.run( name="ICD Analysis Swarm", description="A swarm that analyzes ICD codes", swarm_type="ConcurrentWorkflow", task=patient_symptoms, agents=[ { "agent_name": "ICD-Analyzer", "description": "An agent that analyzes ICD codes", "system_prompt": "You are an expert ICD code analyzer. Your task is to analyze the ICD codes and provide a detailed explanation of the codes.", "model_name": "groq/openai/gpt-oss-120b", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, }, { "agent_name": "ICD-Code-Explainer-Primary", "description": "An agent that provides primary explanations for ICD codes", "system_prompt": "You are an expert ICD code explainer. Your task is to provide a clear and thorough explanation of the ICD codes to the user, focusing on primary meanings and clinical context.", "model_name": "groq/openai/gpt-oss-120b", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, }, { "agent_name": "ICD-Code-Explainer-Secondary", "description": "An agent that provides additional context and secondary explanations for ICD codes", "system_prompt": "You are an expert ICD code explainer. Your task is to provide additional context, nuances, and secondary explanations for the ICD codes, including possible differential diagnoses and related codes.", "model_name": "groq/openai/gpt-oss-120b", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, }, ], ) print(json.dumps(out, indent=4)) ``` ## Swarm Architecture Explained ### Concurrent Workflow This swarm type processes all agents simultaneously: * **ICD-Analyzer**: Analyzes and identifies relevant ICD codes * **ICD-Code-Explainer-Primary**: Provides primary code explanations * **ICD-Code-Explainer-Secondary**: Offers additional context and nuances ### Benefits of Concurrent Processing * **Speed**: All agents work simultaneously for faster results * **Efficiency**: No waiting for sequential completion * **Comprehensive Coverage**: Multiple perspectives delivered together * **Scalability**: Easy to add more parallel agents ## Expected Output The concurrent swarm will provide: * **ICD Code Analysis**: Relevant medical codes for the symptoms * **Primary Explanations**: Clear, clinical context for each code * **Secondary Context**: Additional insights, differential diagnoses, and related codes * **Comprehensive Coverage**: Multiple perspectives on the same medical case ## Use Cases This pattern is ideal for: * **Medical Diagnosis**: Symptom analysis and code identification * **Clinical Documentation**: Medical record coding and validation * **Medical Education**: Teaching ICD code interpretation * **Healthcare Billing**: Accurate medical code assignment * **Clinical Research**: Medical condition classification and analysis ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Customization Ideas Adapt this pattern for: * **Radiology Analysis**: Multiple imaging specialists working in parallel * **Laboratory Results**: Multiple lab technicians analyzing different tests * **Pharmaceutical Review**: Multiple pharmacists reviewing medication interactions * **Surgical Planning**: Multiple specialists planning surgical procedures * **Emergency Response**: Multiple emergency responders coordinating care ## Advanced Concurrent Workflows You can extend this pattern to: * **Dynamic Agent Allocation**: Automatically assign agents based on workload * **Load Balancing**: Distribute tasks evenly across available agents * **Result Aggregation**: Combine parallel results into unified insights * **Quality Assurance**: Multiple agents validating each other's work ## Next Steps After mastering concurrent workflows, explore: * Sequential workflows for dependent tasks * Hierarchical swarms for team coordination * Majority voting for consensus-based decisions * Agent routing for intelligent task distribution * Mixture of agents for specialized expertise combinations # Image Processing with a Marketplace Prompt Source: https://docs.swarms.ai/docs/examples/examples/image-with-marketplace-prompt 3-step tutorial: create a Swarms agent that processes images using a prebuilt prompt from the marketplace This tutorial shows how to run a **vision-capable agent** that uses a **prebuilt prompt from the Swarms marketplace**. You'll encode a local image to base64, configure the agent with a `marketplace_prompt_id`, and get a response (e.g., "What city is this image of?"). <Info> You need an API key and the Python client. Get your key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). Find marketplace prompts on [swarms.world](https://swarms.world) or via the [Query Prompts API](/docs/marketplace/prompts-api#query-prompts). </Info> ## Step 1 — Set up the client and API key Install the client and load your API key from a `.env` file: ```bash theme={null} pip install swarms-client python-dotenv ``` Create a `.env` file in your project root: ```bash theme={null} SWARMS_API_KEY=your-api-key-here ``` Then initialize the Swarms client in your script: ```python theme={null} import os from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) ``` <Note> Keep your API key out of version control. Use `.env` and add `.env` to your `.gitignore`. </Note> ## Step 2 — Encode your image and pick a marketplace prompt Encode your image to base64 (required for the vision API). Use a local file path or replace with your own image: ```python theme={null} import base64 def encode_image_to_base64(image_path: str) -> str: """Encode an image to base64.""" with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode("utf-8") image_path = "img.jpg" # or your image path image_base64 = encode_image_to_base64(image_path) ``` Choose a **marketplace prompt ID** for your agent. The prompt defines the agent's system prompt, name, and description. You can browse prompts on [swarms.world](https://swarms.world) or query them via the [Prompts API](/docs/marketplace/prompts-api). Use a prompt that fits vision or general analysis. Example ID used below: `72021048-6f31-48b6-b624-7732e6f93437`. ## Step 3 — Run the agent with the image and task Build an `agent_config` that uses the marketplace prompt and a vision-capable model, then call `client.agent.run` with your `task` and `img`: ```python theme={null} import json agent_config = { "model_name": "gpt-4.1", "dynamic_temperature_enabled": True, "max_loops": 1, "marketplace_prompt_id": "72021048-6f31-48b6-b624-7732e6f93437", } out = client.agent.run( agent_config=agent_config, task="What city is this image of?", img=image_base64, ) print(json.dumps(out, indent=4)) ``` When `marketplace_prompt_id` is set, the API fetches the prompt from the marketplace and uses it as the agent's system prompt; you don't need to pass `system_prompt`, `agent_name`, or `description` yourself. ## Complete script Here is the full script in one place: <Tabs> <Tab title="Python"> ```python theme={null} import base64 import json import os from dotenv import load_dotenv from swarms_client import SwarmsClient load_dotenv() client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", timeout=1000, ) def encode_image_to_base64(image_path: str) -> str: """Encode an image to base64""" with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode("utf-8") image_path = "img.jpg" image_base64 = encode_image_to_base64(image_path) agent_config = { "model_name": "gpt-4.1", "dynamic_temperature_enabled": True, "max_loops": 1, "marketplace_prompt_id": "72021048-6f31-48b6-b624-7732e6f93437", } out = client.agent.run( agent_config=agent_config, task="What city is this image of?", img=image_base64, ) print(json.dumps(out, indent=4)) ``` </Tab> </Tabs> ## Summary | Step | What you did | | ----- | -------------------------------------------------------------------- | | **1** | Set up `SwarmsClient` with your API key from `.env`. | | **2** | Encoded a local image to base64 and chose a `marketplace_prompt_id`. | | **3** | Ran the agent with `agent_config`, `task`, and `img=image_base64`. | For more details, see [Vision Capabilities](/docs/examples/examples/vision-capabilities) and [Using marketplace prompts with agents](/docs/marketplace/prompts-api#using-marketplace-prompts-with-agents). # Insider Trading Form 4 Monitor: Cluster Buys and Significance Scoring at Scale Source: https://docs.swarms.ai/docs/examples/examples/insider-form4-monitor A SequentialWorkflow that parses every Form 4 filed with the SEC, scores significance against insider history, detects cluster buys, and ships a ranked end-of-day digest to Slack for the price of a takeout dinner. Every weekday at 5:30pm ET, a ranked digest of the day's most-significant insider buys lands in Slack. Total cost per year: less than what a junior analyst makes in a week. ## What This Example Shows * A four-stage `SequentialWorkflow` — Parser → Insider Profile Lookup → Cluster Detector → Signal Scorer — applied to every Form 4 the SEC publishes * How to ingest the EDGAR Form 4 RSS firehose (500-1000 filings/day) without your job choking on it * Insider history lookups that anchor each transaction against the person's prior trading behavior * Cluster-buy detection: multiple distinct insiders buying the same ticker within 30 days * A 0-100 significance score that filters the firehose down to a handful of HIGH conviction signals * `/v1/swarm/batch/completions` running the whole day's filings in a single overnight job <Info> EDGAR publishes 500-1000 Form 4s every trading day. Single-shot `/v1/swarm/completions` calls breach Free-tier rate caps by mid-morning. The batch endpoint is the right tool — note that it requires a premium tier (Pro, Ultra, or Premium) — see [Rate Limits](/docs/documentation/resources/ratelimits) for the per-tier numbers and upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account) for Pro/Ultra/Premium throughput. </Info> ## Why This Matters Cluster insider buying has 30+ years of peer-reviewed alpha behind it — when three or more insiders at the same company open-market-buy stock inside a thirty-day window, forward returns over the next 6-12 months beat the market by a meaningful margin in nearly every cut of the data. The signal is not the hard part. The hard part is the firehose: EDGAR publishes 500-1000 Form 4s per day, the vast majority are options exercises, automatic 10b5-1 sales, or token grants that mean nothing. Filtering 800 filings down to the three that actually matter — a CFO buying open-market for the first time in two years, alongside two directors inside the same week — is a parsing, classification, and scoring problem at scale. That is exactly what a sequential swarm running over a batch endpoint is built for. ## The Architecture ``` EDGAR Form 4 RSS (500-1000/day) │ ▼ batch fetch (one job) │ ▼ /v1/swarm/batch/completions │ ▼ SequentialWorkflow (per filing) ┌──────────────────────────────┐ │ 1. Parser (gpt-4.1-mini) │ │ extract who/what/how much │ │ │ │ │ ▼ │ │ 2. Insider Profile Lookup │ │ (gpt-4.1-mini) │ │ pull prior history │ │ │ │ │ ▼ │ │ 3. Cluster Detector (gpt-4.1)│ │ other insiders, same name │ │ │ │ │ ▼ │ │ 4. Signal Scorer │ │ (claude-sonnet-4-5) │ │ final 0-100 score │ └──────────────────────────────┘ │ ▼ filter score ≥ 75 │ ▼ end-of-day Slack digest ``` ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..." ``` ```python theme={null} import json import os from datetime import datetime, timedelta import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" SLACK_WEBHOOK_URL = os.getenv("SLACK_WEBHOOK_URL") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Each agent calls into one or more of these tools. The schemas are OpenAI function-call shape and are attached per-agent via `tools_list_dictionary`. ```python theme={null} FETCH_FORM4 = { "type": "function", "function": { "name": "fetch_form4", "description": ( "Fetch a parsed Form 4 filing from EDGAR by accession number. " "Returns issuer, reporting person, transaction code, shares, price, " "and post-transaction ownership." ), "parameters": { "type": "object", "properties": { "accession": { "type": "string", "description": "SEC accession number, e.g. 0001127602-25-019844.", } }, "required": ["accession"], }, }, } LOOKUP_INSIDER_HISTORY = { "type": "function", "function": { "name": "lookup_insider_history", "description": ( "Return the prior 24 months of Form 3/4/5 filings for a given insider CIK. " "Each record contains date, ticker, transaction code, shares, and value." ), "parameters": { "type": "object", "properties": { "person_cik": { "type": "string", "description": "10-digit CIK of the reporting person.", } }, "required": ["person_cik"], }, }, } COUNT_RECENT_INSIDER_BUYS = { "type": "function", "function": { "name": "count_recent_insider_buys", "description": ( "Count distinct insiders who have open-market-purchased the ticker " "within the lookback window." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string", "description": "Issuer ticker symbol."}, "days": { "type": "integer", "description": "Lookback window in days. Default 30.", }, }, "required": ["ticker"], }, }, } COMPUTE_AVG_POSITION_SIZE = { "type": "function", "function": { "name": "compute_avg_position_size", "description": ( "Compute the trailing 24-month average dollar size of open-market " "purchases for a single insider." ), "parameters": { "type": "object", "properties": { "person_cik": { "type": "string", "description": "10-digit CIK of the reporting person.", } }, "required": ["person_cik"], }, }, } SCORE_SIGNIFICANCE = { "type": "function", "function": { "name": "score_significance", "description": ( "Compute a 0-100 significance score for a Form 4 transaction. " "Inputs are the parsed transaction, the insider's prior history, " "and any cluster activity at the issuer." ), "parameters": { "type": "object", "properties": { "transaction": { "type": "object", "description": "Parsed Form 4 transaction object.", }, "insider_history": { "type": "object", "description": "Output of lookup_insider_history + compute_avg_position_size.", }, "cluster_data": { "type": "object", "description": "Output of count_recent_insider_buys for the issuer.", }, }, "required": ["transaction", "insider_history", "cluster_data"], }, }, } POST_SLACK_DIGEST = { "type": "function", "function": { "name": "post_slack_digest", "description": ( "Post the ranked end-of-day digest of HIGH conviction insider signals " "to a Slack channel via incoming webhook." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "Header text for the Slack message.", }, "signals_list": { "type": "array", "description": "Ranked list of HIGH conviction signals.", "items": { "type": "object", "properties": { "ticker": {"type": "string"}, "insider": {"type": "string"}, "role": {"type": "string"}, "dollar_value": {"type": "number"}, "score": {"type": "integer"}, "rationale": {"type": "string"}, }, "required": ["ticker", "insider", "score", "rationale"], }, }, }, "required": ["text", "signals_list"], }, }, } ``` ## Step 3: Define the Four Pipeline Agents The first two stages are mechanical parsing and history retrieval — `gpt-4.1-mini` handles them cheaply. Cluster detection needs a stronger model that can reason about overlap windows; `gpt-4.1` does that work. The final significance score is the only step that exercises real judgment, so `claude-sonnet-4-5` gets the closing call. ```python theme={null} PARSER_PROMPT = ( "You are a Form 4 parser. Given an accession number, call fetch_form4 and " "extract: issuer ticker, reporting person name and CIK, role " "(CEO/CFO/Director/Officer/10% Holder), transaction code (P/S/A/M/F), " "shares transacted, price per share, total dollar value, and " "post-transaction ownership. Output strict JSON. Flag whether the " "transaction is an open-market purchase (code P) — anything else is noise " "for this pipeline." ) INSIDER_PROFILE_PROMPT = ( "You are an insider profile analyst. Given the parsed transaction, call " "lookup_insider_history and compute_avg_position_size for the reporting " "person. Append to the JSON: trailing_24m_buy_count, avg_buy_dollars, " "months_since_last_buy, and a one-sentence behavioral note (e.g. 'first " "open-market buy in 27 months', 'consistent monthly buyer')." ) CLUSTER_DETECTOR_PROMPT = ( "You are a cluster-buy detector. Given the enriched transaction, call " "count_recent_insider_buys for the issuer with a 30-day window. Append: " "cluster_size (distinct insiders), cluster_total_dollars, and " "cluster_classification (NONE | EMERGING | STRONG | EXCEPTIONAL). " "EXCEPTIONAL requires 4+ distinct insiders inside 30 days." ) SIGNAL_SCORER_PROMPT = ( "You are the final signal scorer. Given the fully enriched transaction, " "call score_significance and output the final JSON: " '{"ticker": str, "insider": str, "role": str, "dollar_value": float, ' '"score": int (0-100), "conviction": "LOW"|"MEDIUM"|"HIGH", ' '"rationale": str (one sentence)}. ' "Weight cluster_classification heavily — a STRONG cluster with a CFO " "first-buy-in-two-years should score 85+. A solo 10% holder routine buy " "should score under 40." ) def build_form4_pipeline(accession: str) -> dict: return { "name": f"Form 4 Significance Pipeline — {accession}", "description": "Parse, profile, cluster, score one Form 4 filing.", "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": ( f"Process Form 4 accession {accession}. Output the final " f"significance signal as strict JSON." ), "agents": [ { "agent_name": "Form 4 Parser", "description": "Extracts structured transaction data from raw Form 4.", "system_prompt": PARSER_PROMPT, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.1, "tools_list_dictionary": [FETCH_FORM4], }, { "agent_name": "Insider Profile Lookup", "description": "Enriches the transaction with the insider's prior 24m history.", "system_prompt": INSIDER_PROFILE_PROMPT, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.1, "tools_list_dictionary": [LOOKUP_INSIDER_HISTORY, COMPUTE_AVG_POSITION_SIZE], }, { "agent_name": "Cluster Detector", "description": "Counts other insiders buying the same ticker in the last 30 days.", "system_prompt": CLUSTER_DETECTOR_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.2, "tools_list_dictionary": [COUNT_RECENT_INSIDER_BUYS], }, { "agent_name": "Signal Scorer", "description": "Issues the final 0-100 significance score and conviction.", "system_prompt": SIGNAL_SCORER_PROMPT, "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.2, "tools_list_dictionary": [SCORE_SIGNIFICANCE], }, ], } ``` <Note> The Parser and Profile Lookup stages are pure extraction — they almost never need to think. Reserving `claude-sonnet-4-5` for the Signal Scorer is where the cost-per-Form-4 math stays under three cents. </Note> ## Step 4: Process One Form 4 End-to-End Before scaling, prove the pipeline on a single filing. ```python theme={null} def score_one_form4(accession: str) -> dict: payload = build_form4_pipeline(accession) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() result = score_one_form4("0001127602-25-019844") for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600]) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` The Signal Scorer's final JSON is the row you persist. The other three stages are the audit trail — every score is fully reproducible from the parsed filing, the insider history snapshot, and the cluster counts that fed into it. ## Step 5: End-of-Day Batch Pipeline EDGAR's Form 4 RSS feed publishes accession numbers in close to real time. Pull the day's list at 5:30pm ET and submit it in chunks — `/v1/swarm/batch/completions` accepts at most 50 swarms per request. ```python theme={null} EDGAR_FORM4_RSS = ( "https://www.sec.gov/cgi-bin/browse-edgar" "?action=getcurrent&type=4&company=&dateb=&owner=include&count=1000&output=atom" ) def fetch_todays_form4_accessions() -> list[str]: """Pull every Form 4 accession number filed today from EDGAR.""" resp = requests.get( EDGAR_FORM4_RSS, headers={"User-Agent": "InsiderMonitor contact@yourfirm.com"}, timeout=60, ) resp.raise_for_status() # Parse the atom feed for <id>...</id> accession entries. # Implementation omitted — any feedparser/xml.etree call works here. return parse_accessions_from_atom(resp.text) # /v1/swarm/batch/completions accepts at most 50 swarms per request. BATCH_SIZE_LIMIT = 50 def run_eod_batch() -> list[dict]: accessions = fetch_todays_form4_accessions() print(f"Processing {len(accessions)} Form 4 filings for {datetime.utcnow().date()}") payload = [build_form4_pipeline(a) for a in accessions] results = [] for i in range(0, len(payload), BATCH_SIZE_LIMIT): response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload[i:i + BATCH_SIZE_LIMIT], timeout=1800, ) response.raise_for_status() results.extend(response.json()) return results def extract_final_signal(result: dict) -> dict | None: """Pull the Signal Scorer's JSON output from a single batch result. Each item in the batch response is shaped {"status", "swarm_name", "result", "usage"} — the swarm's conversation lives under "result", not "output". """ for output in result.get("result", []): if "Signal Scorer" in output.get("role", ""): content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) try: return json.loads(content) except json.JSONDecodeError: return None return None results = run_eod_batch() signals = [s for s in (extract_final_signal(r) for r in results) if s] high_conviction = sorted( [s for s in signals if s.get("score", 0) >= 75], key=lambda s: s["score"], reverse=True, ) print(f"Total signals scored: {len(signals)}") print(f"HIGH conviction (score >= 75): {len(high_conviction)}") ``` Now ship the digest to Slack. ```python theme={null} def post_digest_to_slack(signals: list[dict]) -> None: if not signals: return today = datetime.utcnow().strftime("%Y-%m-%d") lines = [f"*Insider Form 4 Digest — {today}*", ""] for s in signals[:20]: lines.append( f"• *{s['ticker']}* — {s['insider']} ({s.get('role', '?')}) " f"${s.get('dollar_value', 0):,.0f} — score *{s['score']}* — {s['rationale']}" ) requests.post(SLACK_WEBHOOK_URL, json={"text": "\n".join(lines)}, timeout=30) post_digest_to_slack(high_conviction) ``` Wire the whole thing to cron: ```cron theme={null} 30 17 * * 1-5 /usr/bin/python3 /opt/jobs/form4_monitor.py >> /var/log/form4.log 2>&1 ``` <Info> Run `fetch_todays_form4_accessions` once at 5:30pm ET — that captures the full filing window, since Form 4 has a two-business-day reporting deadline and most issuers file in the last hour before EDGAR's evening cutoff. </Info> ## Real Cost vs. Quantitative Signal Provider Per-Form-4 cost is dominated by the Signal Scorer's `claude-sonnet-4-5` call; the three preceding mini/gpt-4.1 stages add only fractions of a cent. | Scope | Cost | | ------------------------------------------------ | ---------------------- | | Per Form 4 (4-stage SequentialWorkflow) | \~\$0.02 | | Per trading day (\~800 filings) | \~\$16 | | Per year (\~250 trading days) | \~\$4,000 | | Bloomberg Terminal — single seat | \~\$24,000/yr | | Quantitative insider-signal data vendor | \$50,000-\$200,000/yr | | Dedicated insider-trading analyst (fully loaded) | \$150,000-\$250,000/yr | You are buying the same firehose-to-signal transform a quant data vendor sells, for roughly 2% of what they charge — and you own the prompt, the scoring rubric, and the audit trail row-by-row. ## Next Steps * [Build an AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) for the HierarchicalSwarm pattern that turns these signals into long/short calls * [SEC Filing Triage Pipeline](/docs/examples/examples/sec-filing-triage-pipeline) to extend the same batch architecture to 10-K, 10-Q, and 8-K filings * [Sell-Side Research Pipeline](/docs/examples/examples/sell-side-research-pipeline) for the full publish-grade research note built on top of your highest conviction signals # Insurance Claims Triage at Scale Source: https://docs.swarms.ai/docs/examples/examples/insurance-claims-triage Run a single specialized agent across 10,000 claim rows in parallel using /v1/agent/batch/completions — coverage match, fraud signal, and payout estimate per row. ## What This Example Shows * How to map a pandas DataFrame of insurance claims into the batch payload shape * How to call `/v1/agent/batch/completions` with thousands of independent rows * A structured-output prompt that returns coverage match, fraud signal, and a payout estimate * How to write the results back to the original DataFrame in one merge * A real cost comparison against a human claims-adjuster floor <Info> This tutorial uses `/v1/agent/batch/completions` — the highest-throughput endpoint on the platform. It is premium-only and accepts up to 50 tasks per request, so larger workloads are submitted in chunks. For sustained batches above 1,000 rows or production SLAs, upgrade to Pro, Ultra, or Premium at [https://swarms.world/platform/account](https://swarms.world/platform/account) for access and the rate-limit headroom you need. </Info> ## Why This Matters Claims triage is the single largest cost center in P\&C insurance ops. Every incoming claim has to be read, classified, checked against the policy, scored for fraud, and routed — and 80% of them are routine. Adjusters spend most of their day on the boring 80% and run out of bandwidth for the complex 20% that actually need a human. The job is to take that 80% off the floor: a single specialized agent, called once per claim, ten thousand at a time, with structured output your downstream systems can act on directly. The batch endpoint is the perfect fit — every claim is independent, compute per row is small, and the work parallelizes trivially. ## Step 1: Setup ```bash theme={null} pip install requests pandas python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os from typing import Any import pandas as pd import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" if not API_KEY: raise ValueError("SWARMS_API_KEY environment variable is required") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Triage Agent One agent, one job: read a claim, return structured JSON. The prompt is built around the exact downstream schema your claims system needs. ```python theme={null} TRIAGE_SYSTEM_PROMPT = ( "You are a senior P&C insurance claims triage specialist. " "Given a claim record and the relevant policy summary, you output a STRICT JSON " "object with exactly these keys and nothing else:\n\n" "{\n" ' "coverage_match": "COVERED" | "PARTIAL" | "NOT_COVERED",\n' ' "coverage_rationale": "<one sentence citing the policy clause>",\n' ' "fraud_signal": "LOW" | "MEDIUM" | "HIGH",\n' ' "fraud_indicators": ["<short bullet>", "..."],\n' ' "payout_estimate_usd": <integer>,\n' ' "payout_rationale": "<one sentence>",\n' ' "recommended_action": "AUTO_APPROVE" | "ADJUSTER_REVIEW" | "SIU_REFERRAL" | "DENY"\n' "}\n\n" "Be conservative on fraud — only HIGH if multiple indicators align. " "Auto-approve only when coverage is COVERED, fraud is LOW, and payout is under $5,000. " "Output JSON only. No prose." ) def build_agent_payload(claim_row: dict) -> dict: """Map one claim row into the agent batch payload shape.""" task = ( "POLICY SUMMARY:\n" f"{claim_row['policy_summary']}\n\n" "CLAIM RECORD:\n" f"Claim ID: {claim_row['claim_id']}\n" f"Policyholder: {claim_row['policyholder']}\n" f"Loss Type: {claim_row['loss_type']}\n" f"Date of Loss: {claim_row['date_of_loss']}\n" f"Reported Amount: ${claim_row['reported_amount']}\n" f"Description: {claim_row['description']}\n" f"Prior Claims (12mo): {claim_row['prior_claims_12mo']}\n" ) return { "agent_config": { "agent_name": "Claims Triage Specialist", "system_prompt": TRIAGE_SYSTEM_PROMPT, "model_name": "gpt-4.1", "max_tokens": 1024, "temperature": 0.1, }, "task": task, } ``` ## Step 3: Load the Claims CSV A realistic claims feed lives in a database or warehouse — this example uses a CSV but the shape is identical. ```python theme={null} # Example schema: claim_id, policyholder, policy_summary, loss_type, # date_of_loss, reported_amount, description, prior_claims_12mo claims_df = pd.read_csv("claims_inbox.csv") print(f"Loaded {len(claims_df)} claims for triage") ``` <Note> The batch endpoint executes each request's tasks in parallel server-side, up to 50 tasks per request. You do not need to thread the requests on your end — submit each chunk and wait. </Note> ## Step 4: Submit Claims in Chunks Submit in chunks of 50 — the maximum batch size the endpoint accepts per request — which also makes retries cheap if a single chunk fails. ```python theme={null} def run_batch(payloads: list[dict]) -> list[dict]: response = requests.post( f"{BASE_URL}/v1/agent/batch/completions", headers=headers, json=payloads, timeout=900, ) if response.status_code != 200: raise RuntimeError(f"Batch failed: {response.status_code} — {response.text[:300]}") # Response shape: {"batch_id", "total_requests", "execution_time", # "timestamp", "results": [...]} — the per-task outputs live in "results". return response.json()["results"] def triage_dataframe(df: pd.DataFrame, chunk_size: int = 50) -> pd.DataFrame: all_results: list[dict[str, Any]] = [] for start in range(0, len(df), chunk_size): chunk = df.iloc[start : start + chunk_size] payloads = [build_agent_payload(row.to_dict()) for _, row in chunk.iterrows()] print(f"Submitting rows {start}..{start + len(chunk) - 1}") results = run_batch(payloads) all_results.extend(results) return pd.DataFrame(all_results) raw_results = triage_dataframe(claims_df) ``` ## Step 5: Parse and Merge Results Back The agent returns strict JSON in its output — parse it, expand into columns, and join back on `claim_id`. ```python theme={null} def extract_decision(result_row: dict) -> dict: """Pull the JSON decision out of the agent response.""" # Each item in "results" is an AgentCompletionOutput dict — the agent's # text lives under 'outputs'. Keep a fallback to 'output' for robustness. text = result_row.get("outputs") or result_row.get("output") or "" if isinstance(text, list): # Sometimes a list of message dicts — take the last assistant content for item in reversed(text): if isinstance(item, dict) and item.get("role") in ("assistant", "Claims Triage Specialist"): text = item.get("content", "") break if isinstance(text, list): text = " ".join(str(c) for c in text) try: return json.loads(str(text).strip()) except json.JSONDecodeError: return { "coverage_match": "PARSE_ERROR", "fraud_signal": "PARSE_ERROR", "payout_estimate_usd": 0, "recommended_action": "ADJUSTER_REVIEW", } decisions = pd.DataFrame( [extract_decision(r) for r in raw_results.to_dict(orient="records")] ) decisions["claim_id"] = claims_df["claim_id"].values triaged = claims_df.merge(decisions, on="claim_id", how="left") triaged.to_csv("claims_triaged.csv", index=False) print(triaged["recommended_action"].value_counts()) ``` <Info> The result is a single CSV your claims system can ingest directly. Auto-approve rows close the loop without a human ever opening them. Adjuster-review rows land in the queue with structured context already attached. SIU referrals carry the fraud indicators the investigator needs on day one. </Info> ## Real Cost vs. Human Adjuster Floor | Scenario | Cost per claim | Cost per 10,000 claims | Throughput | | ----------------------------------------------------------- | -------------- | ---------------------- | ---------- | | Batch triage agent (GPT-4.1) | \~\$0.015 | \~\$150 | minutes | | One claims adjuster (fully loaded \~\$95k, \~25 claims/day) | \~\$15 | \~\$150,000 | 400 days | | Outsourced BPO triage floor | \~\$3–\$8 | \~\$30,000–\$80,000 | days | You are not eliminating the adjuster floor — you are taking the routine 80% off their plate so the remaining 20% gets the attention it actually needs. That is a 100x cost reduction on the boring half of the work and faster cycle times on the half that matters. ## Next Steps * See the [AI Hedge Fund pipeline](/docs/examples/examples/ai-hedge-fund) for a multi-agent hierarchical variant when each row needs more than one specialist lens * Read the [Real Estate Investment Memo Swarm](/docs/examples/examples/real-estate-investment-memo) for a hierarchical-swarm pattern applied to memos rather than rows * Browse [Batch Agent Completions](/docs/examples/examples/batch-processing) for the underlying batch endpoint mechanics # Intelligence Triage Pipeline for Defense & Gov Source: https://docs.swarms.ai/docs/examples/examples/intelligence-triage-pipeline A four-stage GraphWorkflow that ingests multi-source open reporting, runs parallel regional and technical analysts, stress-tests conclusions with a red team, and produces an executive brief with confidence levels. ## What This Example Shows * A `GraphWorkflow` modeling the analyst workflow used inside intelligence shops: ingest, parallel analysis, red team, synthesis * Three parallel domain analysts (Geopolitical, Cyber, Open-Source HUMINT) running concurrently against the same packet * A dedicated Red Team agent whose only job is to attack the analysts' conclusions before they reach the brief * A Synthesis Editor that produces a structured PIR-style executive brief tagged with confidence levels (HIGH / MODERATE / LOW) * How to scale the same pipeline overnight across a 200-report inbox with concurrent requests to `/v1/graph-workflow/completions` <Warning> **Premium tier required.** `GraphWorkflow` (`/v1/graph-workflow/completions`) is available on Pro, Ultra, and Premium plans. Upgrade or manage your subscription at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Warning> <Warning> **Unclassified use only.** The Swarms API runs on commercial cloud infrastructure. It is suitable for OSINT, PAI, and CUI-appropriate workflows where your data classification policy permits commercial LLM processing. It is **not** an accredited environment for classified information. Do not pass classified, SCI, or export-controlled material through this API. </Warning> ## Why This Matters Every morning, analysts in defense, intelligence, and corporate-security shops face the same job: triage an overnight firehose of open-source reporting — news wires, regional press, vendor threat feeds, social signal, technical indicators — and turn it into a single brief that a principal will read in under five minutes. Most of the day is spent reading, not reasoning. This pipeline does the reading in parallel, runs a red team against itself, and hands the analyst a draft brief with confidence levels they can edit and sign — turning a six-hour triage cycle into a fifteen-minute review. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Pipeline The graph models how a real watch floor works. The intake agent normalizes the raw packet. Three analysts attack it in parallel from different tradecraft angles. A red team agent challenges them. A synthesis editor produces the final brief. ``` [IntakeNormalizer] ──┬──> [GeopoliticalAnalyst] ──┐ ├──> [CyberAnalyst] ├──> [RedTeam] ──> [SynthesisEditor] └──> [OSINTAnalyst] ┘ ``` ```python theme={null} def build_triage_workflow(packet: str) -> dict: return { "name": "Intelligence-Triage-Pipeline", "description": ( "Four-stage triage: normalize packet, three parallel analysts, " "red team challenge, executive brief with confidence levels." ), "task": packet, "agents": [ { "agent_name": "IntakeNormalizer", "description": "Normalizes raw multi-source reporting into a structured packet.", "system_prompt": ( "You are an intelligence intake officer. Read the raw reporting packet " "and produce a normalized brief with: (1) source list with reliability " "rating A-F and credibility 1-6 (Admiralty Code), (2) extracted entities " "(persons, organizations, locations, capabilities), (3) timeline of events " "in ISO-8601, (4) initial topic tags (e.g., GEO-EAP, CYBER-APT, ECON-SANC). " "Be terse. No analytic conclusions." ), "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "GeopoliticalAnalyst", "description": "Regional and political analysis.", "system_prompt": ( "You are a geopolitical analyst. From the normalized packet, identify " "state-actor intent, regional power dynamics, alliance signals, and " "near-term escalation indicators. Tie each judgment to a specific source " "from the packet. Use ICD 203 estimative language ('almost certainly', " "'likely', 'roughly even chance', 'unlikely'). Avoid speculation past " "what the packet supports." ), "model_name": "gpt-4.1", "max_tokens": 3500, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "CyberAnalyst", "description": "Technical indicators and threat-actor analysis.", "system_prompt": ( "You are a cyber threat intelligence analyst. From the packet, extract " "TTPs (map to MITRE ATT&CK where supported), IOCs, suspected actor " "clusters, and targeting patterns. Distinguish observed activity from " "inferred attribution. Flag any attribution as confidence LOW unless " "the packet provides corroborating technical evidence from two or more " "independent sources." ), "model_name": "gpt-4.1", "max_tokens": 3500, "temperature": 0.2, "max_loops": 1, }, { "agent_name": "OSINTAnalyst", "description": "Open-source HUMINT-style pattern analysis from public reporting.", "system_prompt": ( "You are an open-source analyst. From the packet, identify behavioral " "patterns, network associations, public statements, and corroborating " "ground signal (imagery cues, social posts, local press). Distinguish " "first-hand reporting from aggregator restatements. Surface any single-" "source claims that the other analysts may treat as confirmed." ), "model_name": "gpt-4.1", "max_tokens": 3500, "temperature": 0.3, "max_loops": 1, }, { "agent_name": "RedTeam", "description": "Adversarial review of the three analytic lines.", "system_prompt": ( "You are a red team analyst. You have all three analytic lines in front " "of you. Your job is to attack them. For each major judgment: identify " "(1) the strongest competing hypothesis the analysts did not consider, " "(2) any source the analysts over-weighted relative to its Admiralty " "rating, (3) any deception or denial scenario consistent with the same " "evidence. Do not produce a final answer — produce a list of specific " "challenges the synthesis editor must address." ), "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.4, "max_loops": 1, }, { "agent_name": "SynthesisEditor", "description": "Produces the final executive brief with confidence levels.", "system_prompt": ( "You are the senior editor producing the morning brief. Synthesize the " "three analytic lines and explicitly address each red team challenge " "before reaching your judgments. Output format:\n\n" "TITLE: <one-line topic>\n" "TAGS: <region codes, topic codes>\n" "BOTTOM LINE (2-3 sentences):\n" "KEY JUDGMENTS (3-5 bullets, each tagged HIGH/MODERATE/LOW confidence):\n" "OUTLOOK (next 30 days):\n" "INTELLIGENCE GAPS (what would change the assessment):\n" "SOURCING NOTE (which analytic line(s) drove each judgment).\n\n" "Confidence levels follow ICD 203. Do not exceed 400 words total." ), "model_name": "gpt-4.1", "max_tokens": 4000, "temperature": 0.3, "max_loops": 1, }, ], "edges": [ {"source": "IntakeNormalizer", "target": "GeopoliticalAnalyst"}, {"source": "IntakeNormalizer", "target": "CyberAnalyst"}, {"source": "IntakeNormalizer", "target": "OSINTAnalyst"}, {"source": "GeopoliticalAnalyst", "target": "RedTeam"}, {"source": "CyberAnalyst", "target": "RedTeam"}, {"source": "OSINTAnalyst", "target": "RedTeam"}, {"source": "RedTeam", "target": "SynthesisEditor"}, ], "entry_points": ["IntakeNormalizer"], "end_points": ["SynthesisEditor"], "max_loops": 1, } ``` ## Step 3: Run a Single Report A realistic input packet is a concatenation of normalized headlines, vendor advisories, and social signal pulled from your collection tooling. For this tutorial we use a synthetic packet so the example is runnable end-to-end. ```python theme={null} packet = """ RAW REPORTING PACKET — 2026-05-27 0500Z [1] Reuters (A2): Two regional carriers in Country X grounded after reported GPS spoofing along the eastern corridor. No casualties. 2026-05-26 1840Z. [2] Local press (C3, translated): Defense ministry spokesperson denies any related exercise. 2026-05-26 2110Z. [3] Vendor advisory (B2): Threat group cluster TA-Kestrel observed deploying new ICS-focused implant against aviation telemetry vendors in adjacent region. TTPs include T1190, T1133. 2026-05-25. [4] Social signal (D4): Multiple accounts in-region posting imagery of mobile EW vehicles near border. Geolocation pending. [5] Wire (A1): Foreign minister of Country Y issues statement reiterating "all options on the table" re: airspace incidents. 2026-05-27 0200Z. """ payload = build_triage_workflow(packet) response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=payload, timeout=300, ) result = response.json() print(f"Workflow: {result['name']}") print(f"Status: {result['status']}\n") stages = [ ("STAGE 1 — Intake", ["IntakeNormalizer"]), ("STAGE 2 — Parallel Analysis", ["GeopoliticalAnalyst", "CyberAnalyst", "OSINTAnalyst"]), ("STAGE 3 — Red Team", ["RedTeam"]), ("STAGE 4 — Executive Brief", ["SynthesisEditor"]), ] for label, names in stages: print(f"\n{'=' * 60}\n{label}\n{'=' * 60}") for name in names: if name in result.get("outputs", {}): output = result["outputs"][name] if isinstance(output, list): output = " ".join(str(item) for item in output) print(f"\n[{name}]\n{str(output)[:500]}...") usage = result.get("usage", {}) print(f"\nTotal cost: ${usage.get('token_cost', 0):.4f}") print(f"Total tokens: {usage.get('total_tokens', 0)}") ``` <Note> The Red Team agent never produces a final judgment — it produces a list of challenges that the Synthesis Editor must explicitly address. This is the analytic discipline IC analysts call "structured analytic techniques": you cannot get to the brief without first surviving your strongest critic. </Note> ## Step 4: Run the Full Overnight Inbox in Parallel A real watch floor does not run one packet at a time. It runs the whole inbox between midnight and 0500Z so the brief is on desks at 0700. Fan out the same pipeline across every packet with concurrent requests to `/v1/graph-workflow/completions`. ```python theme={null} from concurrent.futures import ThreadPoolExecutor def run_triage(p: str) -> dict: response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=build_triage_workflow(p), timeout=1800, ) return response.json() # Imagine `inbox` is 200 packets pulled from your collection pipeline. inbox = [packet] # replace with your real list with ThreadPoolExecutor(max_workers=10) as pool: briefs = list(pool.map(run_triage, inbox)) print(f"Briefs produced: {len(briefs)}") ``` <Note> Each graph workflow runs as its own request, so the fan-out happens client-side with a thread pool. (`/v1/swarm/batch/completions` accepts a list of standard swarm specifications — it does not run graph workflows.) For 200 packets this typically completes in well under an hour — overnight is more than enough buffer for the morning brief cycle. </Note> ## Step 5: Audit Trail and Cost Reconciliation Procurement and IG reviews almost always ask the same two questions: who ran what, and what did it cost. Two endpoints answer both. ```python theme={null} # Full request history with timestamps, endpoints, and execution metadata logs = requests.get(f"{BASE_URL}/v1/account/logs", headers=headers, timeout=60).json() # Aggregated usage and cost for billing reconciliation usage = requests.get(f"{BASE_URL}/v1/usage/costs", headers=headers, timeout=60).json() ``` Every swarm run is logged with its agent outputs, token counts, and the model used per agent (raw request inputs are not returned by the logs endpoint). This is the same trail your auditor will ask for during a contract review. ## Cost vs. a Human Triage Cycle <Info> **Real numbers.** A typical analyst (fully-loaded GS-13 or contractor equivalent at roughly \$120/hour) spends six hours triaging an overnight inbox of 200 open-source reports — about **\$720 of labor per morning, per analyst**, and most shops staff two to three on the cycle. Running this pipeline across the same 200-report inbox via concurrent `/v1/graph-workflow/completions` requests typically lands in the **low tens of dollars** range total, and produces a draft brief the analyst signs in fifteen minutes instead of writing from scratch. The analyst is still in the loop — but the loop is review-and-sign, not read-and-write. </Info> ## Next Steps * [Graph Workflow Example](/docs/examples/examples/graph-workflow) — more parallel + sequential patterns * [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) — scale any swarm across a full inbox * [Swarm Logs & API History](/docs/examples/examples/swarm-logs) — pull the audit trail for compliance reviews # Legal Document Review Swarm Source: https://docs.swarms.ai/docs/examples/examples/legal-team Learn how to create a sequential workflow swarm that analyzes legal documents with multiple specialized legal experts working in sequence. ## What This Example Shows * Creating a sequential workflow swarm for step-by-step analysis * Implementing multiple specialized legal expert agents * Coordinating agents to work in a specific order * Comprehensive legal document review and analysis ## Installation ```bash theme={null} pip3 install -U swarms-client ``` ## Get Your Swarms API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate a new API key 4. Store it securely in your environment variables ## Code ```python theme={null} """Legal team module for document review and analysis using Swarms API.""" import os from dotenv import load_dotenv import requests # Load environment variables load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"} def run_swarm(swarm_config): """Execute a swarm with the provided configuration.""" response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=HEADERS, json=swarm_config, ) return response.json() def create_legal_review_swarm(document_text): """Create a multi-agent legal document analysis swarm.""" STRUCTURE_ANALYST_PROMPT = """ You are a legal document structure specialist. Your task is to analyze the organization and formatting of the document. - Identify the document type and its intended purpose. - Outline the main structural components (e.g., sections, headers, annexes). - Point out any disorganized, missing, or unusually placed sections. - Suggest improvements to the document's layout and logical flow. """ PARTY_IDENTIFIER_PROMPT = """ You are an expert in identifying legal parties and roles within documents. Your task is to: - Identify all named parties involved in the agreement. - Clarify their roles (e.g., buyer, seller, employer, employee, licensor, licensee). - Highlight any unclear party definitions or relationships. """ CLAUSE_EXTRACTOR_PROMPT = """ You are a legal clause and term extraction agent. Your role is to: - Extract key terms and their definitions from the document. - Identify standard clauses (e.g., payment terms, termination, confidentiality). - Highlight missing standard clauses or unusual language in critical sections. """ AMBIGUITY_CHECKER_PROMPT = """ You are a legal risk and ambiguity reviewer. Your role is to: - Flag vague or ambiguous language that may lead to legal disputes. - Point out inconsistencies across sections. - Highlight overly broad, unclear, or conflicting terms. - Suggest clarifying edits where necessary. """ COMPLIANCE_REVIEWER_PROMPT = """ You are a compliance reviewer with expertise in regulations and industry standards. Your responsibilities are to: - Identify clauses required by applicable laws or best practices. - Flag any missing mandatory disclosures. - Ensure data protection, privacy, and consumer rights are addressed. - Highlight potential legal or regulatory non-compliance risks. """ swarm_config = { "name": "Legal Document Review Swarm", "description": "A collaborative swarm for reviewing contracts and legal documents.", "agents": [ { "agent_name": "Structure Analyst", "description": "Analyzes document structure and organization", "system_prompt": STRUCTURE_ANALYST_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Party Identifier", "description": "Identifies parties and their legal roles", "system_prompt": PARTY_IDENTIFIER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Clause Extractor", "description": "Extracts key terms, definitions, and standard clauses", "system_prompt": CLAUSE_EXTRACTOR_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Ambiguity Checker", "description": "Flags ambiguous or conflicting language", "system_prompt": AMBIGUITY_CHECKER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Compliance Reviewer", "description": "Reviews document for compliance with legal standards", "system_prompt": COMPLIANCE_REVIEWER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, ], "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": f"Perform a legal document review and provide structured analysis of the following contract:\n\n{document_text}", } return run_swarm(swarm_config) def run_legal_review_example(): """Run an example legal document analysis.""" document = """ SERVICE AGREEMENT This Service Agreement ("Agreement") is entered into on June 15, 2024, by and between Acme Tech Solutions ("Provider") and Brightline Corp ("Client"). 1. Services: Provider agrees to deliver IT consulting services as outlined in Exhibit A. 2. Compensation: Client shall pay Provider $15,000 per month, payable by the 5th of each month. 3. Term & Termination: The Agreement shall remain in effect for 12 months and may be terminated with 30 days' notice by either party. 4. Confidentiality: Each party agrees to maintain the confidentiality of proprietary information. 5. Governing Law: This Agreement shall be governed by the laws of the State of California. IN WITNESS WHEREOF, the parties have executed this Agreement as of the date first above written. """ result = create_legal_review_swarm(document) print(result) return result if __name__ == "__main__": run_legal_review_example() ``` ## Swarm Architecture Explained ### Sequential Workflow This swarm type processes agents in a specific order: 1. **Structure Analyst**: Reviews document organization first 2. **Party Identifier**: Identifies involved parties based on structure 3. **Clause Extractor**: Extracts terms after understanding parties 4. **Ambiguity Checker**: Reviews language after understanding content 5. **Compliance Reviewer**: Final review after full document analysis ### Agent Specializations * **Structure Analyst**: Document organization and flow * **Party Identifier**: Legal entity identification and roles * **Clause Extractor**: Key terms and standard clauses * **Ambiguity Checker**: Risk assessment and language clarity * **Compliance Reviewer**: Regulatory and legal standard compliance ## Expected Output The sequential swarm will provide: * **Structured Analysis**: Step-by-step document review * **Comprehensive Coverage**: All aspects of the legal document * **Risk Assessment**: Identification of potential legal issues * **Compliance Review**: Regulatory and best practice adherence * **Actionable Recommendations**: Specific improvements and clarifications ## Use Cases This pattern is ideal for: * **Contract Review**: Service agreements, employment contracts, NDAs * **Legal Compliance**: Regulatory documentation, policy reviews * **Due Diligence**: Merger and acquisition document analysis * **Risk Assessment**: Identifying legal vulnerabilities and ambiguities * **Document Standardization**: Ensuring consistent legal language ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Customization Ideas Adapt this pattern for: * **Financial Documents**: Loan agreements, investment contracts * **Real Estate**: Purchase agreements, lease contracts * **Intellectual Property**: Licensing agreements, patent documentation * **Employment Law**: HR policies, employment contracts * **Regulatory Compliance**: Industry-specific compliance documents ## Next Steps After mastering sequential workflows, explore: * Concurrent workflows for parallel analysis * Hierarchical swarms for team coordination * Majority voting for consensus-based decisions * Agent routing for dynamic task distribution # List Your Agents Source: https://docs.swarms.ai/docs/examples/examples/list-agents 3-step quick start to list agents you created ## Step 1 — Get your API key Create an API key in your dashboard: `https://swarms.world/platform/api-keys` ## Step 2 — Add it to .env ```bash theme={null} SWARMS_API_KEY=your-api-key-here ``` ## Step 3 — Run the code <Tabs> <Tab title="Python"> ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() BASE_URL = "https://api.swarms.world" headers = { "x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json", } resp = requests.get(f"{BASE_URL}/v1/agents/list", headers=headers) print(resp.status_code) data = resp.json() print(json.dumps(data, indent=2)) print(f"Number of agents: {data.get('count')}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} require('dotenv').config(); const BASE_URL = "https://api.swarms.world"; const API_KEY = process.env.SWARMS_API_KEY; async function main() { const res = await fetch(`${BASE_URL}/v1/agents/list`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' } }); console.log(res.status); const data = await res.json(); console.log(JSON.stringify(data, null, 2)); console.log(`Number of agents: ${data.count}`); } main().catch(console.error); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X GET "https://api.swarms.world/v1/agents/list" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" ``` </Tab> </Tabs> # LLM Council Example Source: https://docs.swarms.ai/docs/examples/examples/llm-council Build a multi-model council with peer review and synthesis using LLMCouncil ## Investment Strategy Council This example demonstrates how to use LLMCouncil to get independent responses from multiple agents, have them peer-review and rank each other's work, then synthesize the best elements into a final answer — inspired by [Andrej Karpathy's llm-council](https://github.com/karpathy/llm-council) concept. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define the Council Create council members with distinct perspectives. Each member will independently answer the query, then review and rank all anonymized responses before a chairman synthesizes the final answer: ```python theme={null} def run_llm_council(question: str) -> dict: """Run a multi-model council with peer review and synthesis.""" swarm_config = { "name": "Investment Strategy Council", "description": "Multi-model council for investment analysis", "swarm_type": "LLMCouncil", "task": question, "agents": [ { "agent_name": "Analytical Councilor", "description": "Deep analytical thinker focused on comprehensive coverage", "system_prompt": """You are a member of an LLM Council. Provide comprehensive, analytical responses. Your strengths: - Deep analytical thinking and thorough exploration of multiple perspectives - Rich contextual understanding and detailed breakdowns - Evidence-based reasoning with data points Provide detailed, well-structured responses. You are part of a council where multiple agents will respond to the same query, then evaluate each other's responses. Focus on depth and accuracy.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.7 }, { "agent_name": "Concise Councilor", "description": "Clear and structured communicator focused on efficiency", "system_prompt": """You are a member of an LLM Council. Provide concise, well-structured responses. Your strengths: - Clear and structured communication - Efficient information processing with high signal-to-noise ratio - Well-organized presentation with actionable takeaways Provide concise but complete answers. You are part of a council where multiple agents will respond to the same query, then evaluate each other's responses. Focus on clarity and efficiency.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 }, { "agent_name": "Balanced Councilor", "description": "Thoughtful and nuanced perspective with trade-off analysis", "system_prompt": """You are a member of an LLM Council. Provide thoughtful, balanced responses. Your strengths: - Nuanced understanding and balanced perspectives - Thoughtful consideration of trade-offs, risks, and limitations - Clear reasoning with both pros and cons Provide balanced, well-reasoned responses. You are part of a council where multiple agents will respond to the same query, then evaluate each other's responses. Focus on nuance and fairness.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6 }, { "agent_name": "Creative Councilor", "description": "Innovative thinker with unique perspectives", "system_prompt": """You are a member of an LLM Council. Provide creative, innovative perspectives. Your strengths: - Creative problem-solving and innovative thinking - Unique perspectives and out-of-the-box approaches - Connecting seemingly unrelated concepts for novel insights Provide creative and innovative responses. You are part of a council where multiple agents will respond to the same query, then evaluate each other's responses. Focus on originality and fresh insights.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.8 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=300 ) return response.json() ``` ### Step 4: Run the Council ```python theme={null} # Define the question question = """ What are the most promising renewable energy investment opportunities for 2025, considering both risk and return potential? """ # Run council result = run_llm_council(question) # Display the council's workflow for output in result.get("output", []): role = output["role"] content = output["content"] print(f"\n{'='*60}") print(f"{role}") print(f"{'='*60}") if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:800] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` ============================================================ Analytical Councilor ============================================================ COMPREHENSIVE RENEWABLE ENERGY INVESTMENT ANALYSIS 1. SOLAR ENERGY (Risk: Low-Medium, Return: 8-15%) - Utility-scale solar continues 20%+ annual growth - Key players: First Solar (FSLR), Enphase Energy (ENPH) - Catalyst: IRA tax credits extending through 2032 - Risk factors: Panel oversupply from China, interest rate sensitivity on project financing 2. BATTERY STORAGE (Risk: Medium, Return: 12-25%) - Grid-scale storage is the critical enabler for renewables - Market growing at 35% CAGR through 2030 - Key players: Tesla Energy, Fluence Energy (FLNC) - Risk factors: Lithium price volatility, technology shifts... ============================================================ Concise Councilor ============================================================ TOP 5 RENEWABLE ENERGY PLAYS FOR 2025 | Sector | Risk | Return | Top Pick | |-----------------|--------|----------|------------------| | Solar | Low | 8-15% | First Solar | | Battery Storage | Medium | 12-25% | Fluence Energy | | Offshore Wind | Medium | 10-18% | Orsted | | Green Hydrogen | High | 20-40% | Plug Power | | Nuclear/SMR | High | 15-30% | NuScale Power | Best risk-adjusted: Solar + Battery Storage combo. Highest upside: Green Hydrogen (but volatile)... ============================================================ Balanced Councilor ============================================================ BALANCED ASSESSMENT: RENEWABLE ENERGY INVESTMENTS The renewable energy sector presents genuine opportunities but requires careful risk management. Here's a balanced view: FAVORABLE FACTORS: - Policy tailwinds (IRA, EU Green Deal) provide multi-year visibility - Technology costs declining 5-10% annually across solar and wind - Corporate PPA demand at all-time highs CAUTIONARY FACTORS: - Many clean energy stocks trade at premium valuations - Interest rate sensitivity — renewables are capital-intensive - Supply chain concentration risks (China dominates solar, rare earths) RECOMMENDATION: A barbell approach — combine low-risk solar/wind ETFs (60%) with selective high-growth bets in storage and hydrogen (40%). Avoid overconcentration in any single technology... ============================================================ Creative Councilor ============================================================ UNCONVENTIONAL RENEWABLE ENERGY OPPORTUNITIES Beyond the obvious solar/wind plays, consider these overlooked angles: 1. AGRIVOLTAICS — Solar panels over farmland. Dual revenue from energy + agriculture. Early-stage but massive TAM. Watch for startups combining precision agriculture with solar. 2. VEHICLE-TO-GRID (V2G) — Every EV becomes a distributed battery. Utilities will pay EV owners to stabilize the grid. Companies enabling this infrastructure are undervalued. 3. ENHANCED GEOTHERMAL — Fervo Energy's breakthrough in hot rock drilling makes geothermal viable anywhere, not just volcanic regions. 24/7 clean baseload power — the holy grail... ============================================================ Analytical Councilor-Evaluation ============================================================ RANKINGS: 1. Response C: Most balanced and practical — acknowledges both opportunities and risks. The barbell strategy is actionable. 2. Response A: Thorough and data-rich, but lacks risk hedging discussion. 3. Response D: Creative and differentiated perspectives, but speculative without risk quantification. 4. Response B: Clear and concise, but oversimplified for an investment decision of this complexity... ============================================================ Chairman ============================================================ FINAL SYNTHESIZED RESPONSE: RENEWABLE ENERGY INVESTMENT OPPORTUNITIES FOR 2025 Drawing from all council member perspectives and their peer evaluations, here is the synthesized recommendation: CORE PORTFOLIO (60% allocation — Lower Risk): - Utility-scale Solar: 8-15% return potential, policy-backed - Battery Storage: 12-25% return, critical grid enabler - Diversified Clean Energy ETFs for broad exposure GROWTH ALLOCATION (30% — Medium Risk): - Offshore Wind: 10-18% return, massive European pipeline - Grid modernization plays SPECULATIVE (10% — Higher Risk, Higher Reward): - Green Hydrogen: 20-40% upside but volatile - Enhanced Geothermal: Breakthrough potential - Agrivoltaics and V2G infrastructure KEY INSIGHT FROM COUNCIL: The most valuable contribution came from combining the analytical depth of traditional sector analysis with the creative councilor's identification of overlooked opportunities like agrivoltaics and V2G... Total cost: $0.3215 ``` ### How LLMCouncil Works The council follows a 3-phase workflow: ``` Phase 1: INDEPENDENT RESPONSE ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Councilor A │ │ Councilor B │ │ Councilor C │ │ Councilor D │ │ (Analytical) │ │ (Concise) │ │ (Balanced) │ │ (Creative) │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ ▼ ▼ ▼ ▼ Response A Response B Response C Response D Phase 2: PEER REVIEW (anonymized) Each councilor ranks ALL responses (including their own) Responses are anonymized so councilors judge on quality alone Phase 3: SYNTHESIS ┌──────────────────────────────────────────────────────────────────┐ │ CHAIRMAN │ │ Reviews all responses + all rankings → Final synthesized answer │ └──────────────────────────────────────────────────────────────────┘ ``` <Note> LLMCouncil is inspired by Andrej Karpathy's llm-council concept. Each agent responds independently, then all agents peer-review and rank each other's anonymized responses. A chairman agent synthesizes everything — original responses plus rankings — into a final answer that incorporates the strongest elements from each perspective. This multi-phase approach produces higher-quality outputs than any single agent alone. </Note> # M&A Due Diligence Swarm Source: https://docs.swarms.ai/docs/examples/examples/ma-due-diligence A cross-functional hierarchical swarm where a Deal Lead synthesizes Financial, Legal, Tax, and Technical findings into a single deal memo with go/no-go recommendation. ## What This Example Shows * A `HierarchicalSwarm` modeling a real **M\&A diligence team**, not a single-discipline review * A Deal Lead (director) coordinating four specialist workers: Financial Analyst, Legal Counsel, Tax Counsel, and Technical Auditor * How the director **synthesizes** parallel findings into one structured deal memo: red flags, financial highlights, legal risks, and go / no-go / conditional * How to fan the same swarm across a **portfolio of targets** overnight using `/v1/swarm/batch/completions` * Concrete cost-per-target versus a real mid-market diligence engagement <Info> This example runs on premium swarm infrastructure, and the batch endpoint at the end requires a Pro / Ultra / Premium plan. Manage your plan and credits at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Info> ## Why This Matters A mid-market M\&A diligence engagement typically runs **\$150,000 to \$500,000+** across legal, financial, tax, and technical advisors, with partner-level attorney rates of **\$800 to \$1,500 per hour** and Big-Four diligence fees in similar ranges. Most of that spend goes into the **first-pass screen** — the read that decides whether the target is even worth a full diligence engagement. That first-pass screen is exactly the job this swarm does: cross-functional, structured, opinionated, and cheap enough to run on every target in your pipeline. The differentiator versus a single-discipline legal-review swarm is that **deals are killed by tax exposure, broken financials, or tech debt as often as by legal risk** — you need all four lenses simultaneously, with one synthesizer at the top. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` Create a `.env` file: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` Get your key at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ## Step 2: Configure the Client ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 3: Describe the Target ```python theme={null} target_brief = """ Target: NorthArc Logistics, Inc. Sector: Mid-market last-mile B2B logistics, U.S. Midwest Stage: Profitable, founder-owned, 12 years old Headline financials (target-provided, unaudited): - TTM revenue: $84M, growing 11% YoY - TTM EBITDA: $9.8M (11.7% margin) - Net working capital: $6.1M - Long-term debt: $14M (senior secured, 7.25% fixed) - Customer concentration: top 3 customers = 47% of revenue Asking price: $78M cash-free debt-free, plus working-capital peg. Strategic context: - Acquirer is a PE-backed national logistics roll-up at $400M revenue. - Two prior LOIs on the same target broke in diligence (reason unknown). - Founder will roll 20% equity and stay for a 2-year earnout. Known issues raised by sell-side banker: - Two trucks involved in 2023 multi-vehicle accident, litigation ongoing. - Recent state sales-tax audit closed, but federal nexus question raised by acquirer's tax advisor. - Custom dispatch software built in-house; no vendor, two engineers on payroll maintain it. - One union shop (one of three terminals), CBA expires in 14 months. Deliverable: structured deal memo with go / no-go / conditional recommendation and the three deal-breaker items to clear before LOI. """ ``` ## Step 4: Build the Diligence Team The Deal Lead is intentionally constrained to **synthesis and a recommendation** — not redoing the workstreams. Each specialist owns one lane. ```python theme={null} payload = { "name": "M&A Due Diligence Swarm", "description": ( "Cross-functional diligence: Deal Lead synthesizes Financial, " "Legal, Tax, and Technical findings into a single deal memo." ), "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( "Conduct a first-pass M&A diligence on the target below. Each " "specialist should produce findings strictly within their domain. " "The Deal Lead must produce a structured deal memo with: " "(1) top red flags ranked by severity, (2) financial highlights " "and quality-of-earnings concerns, (3) legal, tax, and technical " "risks, (4) a go / no-go / conditional recommendation with the " "three specific items that must be cleared before signing an LOI, " "and (5) suggested valuation adjustments.\n\n" f"TARGET BRIEF:\n{target_brief}" ), "agents": [ { "agent_name": "Deal Lead", "description": ( "Diligence partner. Reviews each workstream, reconciles " "conflicts, and writes the single deal memo." ), "system_prompt": ( "You are the Deal Lead on this M&A engagement. You do NOT " "redo the specialists' work. Your job is to: " "(1) rank red flags across all four workstreams by deal " "impact, (2) reconcile disagreements, (3) deliver a " "go / no-go / conditional recommendation, (4) name the " "three specific items that must clear before signing an " "LOI, and (5) propose any valuation adjustments. Output " "a structured memo. Be decisive. No hedging without " "naming the specific data you would need to decide." ), "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Financial Analyst", "description": "Quality of earnings, working capital, debt.", "system_prompt": ( "You are an M&A financial analyst. Focus on quality of " "earnings, working-capital normalizations, customer " "concentration risk, EBITDA add-backs that are likely " "to be challenged, and debt structure. Identify the top " "QoE concerns and the specific schedules you would need " "from the sell-side data room to clear them. Do not " "comment on legal, tax, or technology matters." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Legal Counsel", "description": "Corporate, litigation, employment, regulatory.", "system_prompt": ( "You are M&A legal counsel. Focus on litigation exposure, " "the union CBA expiring in 14 months, employment and " "change-of-control issues, material contracts, customer " "assignability, and regulatory matters. Identify the top " "legal red flags and the documents you would request " "first. Do not comment on financial, tax, or technical " "matters." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Tax Counsel", "description": "Federal, state, sales/use, structuring.", "system_prompt": ( "You are M&A tax counsel. Focus on the federal sales-tax " "nexus question, multi-state exposure for a logistics " "operator, deal-structure implications (stock vs asset, " "338(h)(10), F-reorg), the founder's rollover equity, " "and any indemnity / escrow recommendations for tax " "contingencies. Quantify exposure where possible. Do not " "comment on financial, legal, or technical matters." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Technical Auditor", "description": "Tech stack, key-person risk, integration.", "system_prompt": ( "You are a technical diligence auditor. Focus on the " "in-house dispatch software: key-person risk on the two " "engineers, code ownership and IP assignment, scalability " "to the acquirer's $400M roll-up, integration cost, and " "the build-vs-buy decision post-close. Identify the top " "technical risks and the artifacts you would request " "(architecture docs, code review, runbooks). Do not " "comment on financial, legal, or tax matters." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, ], } ``` ## Step 5: Run the Diligence ```python theme={null} response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) result = response.json() for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` <Note> Workers do not see each other's drafts. The Deal Lead sees every specialist output and writes the final memo. This is the right shape for first-pass diligence: independent workstreams in parallel, then one synthesizer. </Note> ## The Cost Story | Resource | Real-world cost | This swarm | | ---------------------------------------- | ---------------------- | ----------------------------------- | | Partner-level M\&A attorney (first read) | \$800 – \$1,500 / hour | Included | | Quality-of-earnings work (Big-Four) | \$50,000 – \$150,000 | Included | | Tax structuring memo | \$25,000 – \$75,000 | Included | | Technical diligence (boutique) | \$25,000 – \$100,000 | Included | | **Per-target first-pass screen** | **\$150K – \$500K+** | **Typically a few dollars or less** | The swarm does not replace your advisors. It replaces the **decision of whether to spend \$150K on advisors**. At a few dollars per run, you can screen every target your bankers send you instead of only the ones that already look interesting — which is where most missed deals hide. ## Step 6: Run a Portfolio Overnight The biggest practical win of this pattern is running it as a **batch across every target in your pipeline**. Same swarm config, list of tasks, one API call. Results land in your inbox in the morning. ```python theme={null} # Three additional target briefs from your pipeline target_brief_2 = "Target: BlueShore Foods... [your second target]" target_brief_3 = "Target: Helix Industrial... [your third target]" briefs = [target_brief, target_brief_2, target_brief_3] def make_task(brief: str) -> str: return ( "Conduct a first-pass M&A diligence on the target below. " "Produce the deal memo per the swarm spec.\n\n" f"TARGET BRIEF:\n{brief}" ) batch_payload = [{**payload, "task": make_task(b)} for b in briefs] batch_response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=batch_payload, timeout=1800, ) for i, deal_result in enumerate(batch_response.json()): print(f"\n=== TARGET {i + 1} ===") print( f"Cost: ${deal_result['usage']['billing_info']['total_cost']:.4f} | " f"Status: {deal_result['status']}" ) ``` <Warning> The `/v1/swarm/batch/completions` endpoint is a premium feature requiring a Pro, Ultra, or Premium plan. See [Premium Endpoints](/docs/documentation/resources/premium-endpoints) and manage your plan at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Warning> ## Differentiation From Related Examples * The [Legal Document Review Swarm](/docs/examples/examples/legal-team) is a *sequential, legal-only* contract review. This swarm is *hierarchical and cross-functional* — finance, tax, and technical specialists work alongside legal, because deals are killed by all four. * The [Supply Chain Hierarchical Swarm](/docs/examples/examples/supply-chain-swarm) uses the same architectural pattern in a different domain — useful as a template for any cross-functional analyst team. ## Next Steps * Read [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) for the full portfolio-mode pattern * Try [Claude Opus 4.8](/docs/examples/examples/claude-opus-4-8) as the model for the Deal Lead for sharper synthesis * Adapt to other professional-services workflows using the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) # Macro Data Release Reaction Engine: CPI, NFP, and FOMC in Under 60 Seconds Source: https://docs.swarms.ai/docs/examples/examples/macro-data-release-engine A scheduled, latency-critical reasoning swarm that parses the release the moment it crosses, models regime impact with Opus 4.8 high, and fans out asset-class trade theses to Slack before the desk has finished reading the headline. ## What This Example Shows * A scheduled engine fired exactly at the release minute (CPI 8:30 AM ET, NFP 8:30 AM ET, FOMC 2:00 PM ET) that parses the print within 5 seconds * A single hypothesis reasoning agent on `claude-opus-4-8` with `reasoning_effort: "high"` to compute surprise vs. consensus and articulate the regime hypothesis * A `GraphWorkflow` that branches by regime into four asset-class workers — Rates, FX, Equities, Commodities — with diversified models per desk * Multiple data sources stitched in via function tools: BLS, FRED, consensus, historical reaction tables, live market snapshots * A full sub-60-second end-to-end budget from release timestamp to a Slack-ready trade brief * Roughly eight dollars per event, \~50 high-stakes events per year — the kind of capability a macro desk pays a strategist \$400k for <Info> `reasoning_effort: "high"` on `claude-opus-4-8` and `GraphWorkflow` are **Premium-only** features. Latency-critical events also benefit from priority processing on the Premium tier. See the [Reasoning Agents tutorial](/docs/examples/examples/reasoning-agents-tutorial) for the full primer on reasoning-effort tuning, and [upgrade your account](https://swarms.world/platform/account) before running this in production. </Info> ## Why This Matters The first ninety seconds after a macro print is where the alpha lives. CPI crosses at 8:30:00.000 ET and by 8:30:30 the front-end of the curve has already moved twenty basis points. No human can physically read the release, decompose the surprise versus consensus across headline / core / shelter / services-ex-shelter, model the regime impact across rates / FX / equities / commodities, and route a tradeable thesis to four desks inside that window — and the desks that try are paying a senior strategist mid-six-figures to be wrong half the time on adrenaline. This engine collapses the whole loop into a deterministic, scheduled call: a reasoning agent computes the surprise and the regime hypothesis with deliberate chains of thought, then a graph fans the hypothesis into asset-specific theses in parallel. By the time CPI prints, your Slack already has a regime-tagged FX/rates/equities/commodities trade brief — and you spent eight dollars to get it. ## The Architecture ```text theme={null} Scheduled trigger (release time, ET) │ ▼ [ReleaseFetcher] (BLS / FRED / consensus / history) │ ▼ [HypothesisReasoner — Opus 4.8 high] (surprise vs. consensus, regime hypothesis) │ ┌────────────────┼────────────────┐ ▼ ▼ ▼ ▼ [RatesStrategist] [FXStrategist] [EquityStrategist] [CommodityStrategist] gpt-4.1 grok-4 sonnet-4.5 gpt-4.1-mini └────────────────┼────────────────┘ ▼ [ThesisSynthesizer — sonnet-4.5] │ ▼ post_slack_alert() ``` Three things to notice. First, the reasoning step is a single dedicated node — that is where the deliberation budget goes, not on every downstream worker. Second, the four asset workers run on diversified models on purpose: real-time edge for FX (grok-4), cheap commodities (gpt-4.1-mini), strong reasoning for equities (sonnet-4.5), structured rates work (gpt-4.1). Third, the entire DAG is one API call — one billing event, one `job_id`, one replayable artifact for the compliance log. ## Step 1: Setup Premium API key, a calendar source for release timestamps, and the standard Python stack. ```bash theme={null} pip install requests python-dotenv pytz export SWARMS_API_KEY="your-premium-api-key" export BLS_API_KEY="your-bls-api-key" export FRED_API_KEY="your-fred-api-key" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..." ``` ```python theme={null} import json import os import time from datetime import datetime, timedelta import requests import pytz from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" ET = pytz.timezone("America/New_York") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` The economic calendar (release\_id, scheduled time ET, release window) can be sourced from any pro vendor — BLS publishes its own forward-looking schedule and FOMC dates are public. For this tutorial assume `RELEASE_CALENDAR` is a list of `{"release_id": "CPI", "ts_et": "2026-06-12T08:30:00"}` records. ## Step 2: Define the Function Tools Seven tools cover the entire pipeline: four data fetchers, two lookups, one notifier. All in OpenAI function format so any agent in the swarm can call them. ```python theme={null} FETCH_BLS_CPI = { "type": "function", "function": { "name": "fetch_bls_cpi", "description": ( "Fetch the latest CPI release from BLS. Returns headline MoM, " "core MoM, headline YoY, core YoY, and the shelter and " "services-ex-shelter components." ), "parameters": { "type": "object", "properties": { "release_month": { "type": "string", "description": "Release month in YYYY-MM format.", }, }, "required": ["release_month"], }, }, } FETCH_BLS_NFP = { "type": "function", "function": { "name": "fetch_bls_nfp", "description": ( "Fetch the latest Nonfarm Payrolls release from BLS. Returns " "headline payrolls change, unemployment rate, labor force " "participation, average hourly earnings MoM and YoY, and prior " "two months' revisions." ), "parameters": { "type": "object", "properties": { "release_month": { "type": "string", "description": "Release month in YYYY-MM format.", }, }, "required": ["release_month"], }, }, } FETCH_FRED_SERIES = { "type": "function", "function": { "name": "fetch_fred_series", "description": ( "Fetch any FRED time series by series_id (e.g., DGS10, DFF, " "DEXUSEU, VIXCLS). Returns the most recent value and the " "trailing 90-day window for regime context." ), "parameters": { "type": "object", "properties": { "series_id": { "type": "string", "description": "FRED series identifier.", }, }, "required": ["series_id"], }, }, } LOOKUP_CONSENSUS = { "type": "function", "function": { "name": "lookup_consensus", "description": ( "Look up the Wall Street consensus expectation for a given " "macro release (Bloomberg/Reuters survey median, mean, and " "high-low range)." ), "parameters": { "type": "object", "properties": { "release_id": { "type": "string", "description": "Release identifier (CPI, NFP, FOMC, GDP, PCE).", }, "release_date": { "type": "string", "description": "Release date in YYYY-MM-DD format.", }, }, "required": ["release_id", "release_date"], }, }, } LOOKUP_HISTORICAL_REACTION = { "type": "function", "function": { "name": "lookup_historical_reaction", "description": ( "Look up the empirical asset-class reaction in the 60 minutes " "post-release for comparable historical surprises in the same " "regime. Returns medians and 25/75 percentiles for 2y, 10y, " "DXY, SPX, gold, and crude moves." ), "parameters": { "type": "object", "properties": { "release_id": {"type": "string"}, "surprise_zscore": { "type": "number", "description": "Standardized surprise (actual - consensus) / historical_std.", }, "regime": { "type": "string", "description": "Current regime tag (e.g., 'hiking', 'cutting', 'pause', 'risk-on', 'risk-off').", }, }, "required": ["release_id", "surprise_zscore", "regime"], }, }, } FETCH_MARKET_SNAPSHOT = { "type": "function", "function": { "name": "fetch_market_snapshot", "description": ( "Fetch a live pre-release market snapshot for an asset class. " "Returns levels, 1-day and 1-week changes, implied vol, and " "positioning indicators." ), "parameters": { "type": "object", "properties": { "asset_class": { "type": "string", "enum": ["rates", "fx", "equities", "commodities"], }, }, "required": ["asset_class"], }, }, } POST_SLACK_ALERT = { "type": "function", "function": { "name": "post_slack_alert", "description": ( "Post the synthesized trade brief to a Slack channel via " "incoming webhook. Use markdown formatting." ), "parameters": { "type": "object", "properties": { "channel": { "type": "string", "description": "Slack channel (e.g., '#macro-desk').", }, "text": { "type": "string", "description": "The formatted trade brief.", }, }, "required": ["channel", "text"], }, }, } ALL_TOOLS = [ FETCH_BLS_CPI, FETCH_BLS_NFP, FETCH_FRED_SERIES, LOOKUP_CONSENSUS, LOOKUP_HISTORICAL_REACTION, FETCH_MARKET_SNAPSHOT, POST_SLACK_ALERT, ] ``` ## Step 3: Define the Hypothesis Reasoning Agent This is the only place in the pipeline that thinks slowly. Its job is narrow and load-bearing: compute the surprise versus consensus on every relevant sub-component, anchor it in the prevailing regime (hiking/cutting/pause, risk-on/off), and produce a single regime-tagged hypothesis the four downstream desks can branch off. `reasoning_effort: "high"` is the lever that buys the deliberate chain — the agent will internally consider multiple regime narratives before committing. ```python theme={null} HYPOTHESIS_PROMPT = ( "You are the senior macro strategist running the post-release " "hypothesis desk. Given a fresh macro print, you must produce a " "single regime-tagged hypothesis in under 15 seconds. Process:\n\n" "1. Call the appropriate fetcher (fetch_bls_cpi, fetch_bls_nfp, or " " fetch_fred_series) to obtain the actual print.\n" "2. Call lookup_consensus to obtain Wall Street consensus.\n" "3. Compute the standardized surprise (actual - consensus) / std for " " every relevant sub-component.\n" "4. Call fetch_fred_series for the current rate regime context (DFF, " " DGS2, DGS10) and risk regime (VIXCLS, DXY).\n" "5. Call lookup_historical_reaction with your computed surprise and " " regime tag.\n" "6. Emit a single JSON object with fields: surprise_summary, " " regime_tag, primary_hypothesis (one sentence), and " " confidence ('low'|'medium'|'high').\n\n" "Do NOT recommend trades — that is the job of the asset-class desks. " "Your output is the regime hypothesis they branch on. Be surgical." ) HYPOTHESIS_AGENT = { "agent_name": "HypothesisReasoner", "description": "Computes the surprise and regime hypothesis.", "system_prompt": HYPOTHESIS_PROMPT, "model_name": "claude-opus-4-8", "reasoning_effort": "high", "max_loops": 1, "max_tokens": 4000, "temperature": 0.2, "tools_list_dictionary": [ FETCH_BLS_CPI, FETCH_BLS_NFP, FETCH_FRED_SERIES, LOOKUP_CONSENSUS, LOOKUP_HISTORICAL_REACTION, ], } ``` <Note> `reasoning_effort: "high"` is the difference between a strategist who blurts out a number and one who sits with the release for ten seconds and says "the headline is hot but services-ex-shelter is decelerating — this is a Fed-friendly miss dressed as a hawkish print." That second read is what the downstream desks branch on. You do not want that on a fast model. </Note> ## Step 4: Define the Graph Workflow Four asset-class strategists fan out from the hypothesis, then a synthesizer collapses their theses into a single Slack-ready brief. Model selection per desk is deliberate: | Desk | Model | Why | | ----------- | ------------------- | --------------------------------------------------------------- | | Rates | `gpt-4.1` | Structured, numerate, strong on yield-curve mechanics | | FX | `xai/grok-4` | Real-time edge — picks up the live tape and positioning chatter | | Equities | `claude-sonnet-4-5` | Best at sector rotation reasoning under regime shifts | | Commodities | `gpt-4.1-mini` | Cheap and adequate — commodities reaction is mostly mechanical | | Synthesizer | `claude-sonnet-4-5` | Needs to read four theses and write one tight brief | ```python theme={null} RATES_PROMPT = ( "You are the rates desk strategist. Given the regime hypothesis, " "call fetch_market_snapshot('rates') and produce a single trade " "thesis in under 5 seconds: front-end vs. back-end positioning, " "specific instrument (2y, 5y, 10y futures or swaps), direction, " "size guidance, stop, and time horizon. Max 80 words. Be specific." ) FX_PROMPT = ( "You are the FX desk strategist. Given the regime hypothesis, call " "fetch_market_snapshot('fx') and produce a single trade thesis in " "under 5 seconds: which pair, direction, entry level, stop, size, " "and the carry/momentum lens that drives the call. Max 80 words. " "Be specific." ) EQUITY_PROMPT = ( "You are the equity desk strategist. Given the regime hypothesis, " "call fetch_market_snapshot('equities') and produce a single trade " "thesis in under 5 seconds: sector rotation call, specific " "instrument (futures, ETF, or pair), direction, stop, and how the " "regime shift cascades through cyclicals vs. defensives. Max 80 " "words. Be specific." ) COMMODITY_PROMPT = ( "You are the commodity desk strategist. Given the regime hypothesis, " "call fetch_market_snapshot('commodities') and produce a single " "trade thesis in under 5 seconds: gold or crude or both, direction, " "specific instrument, stop, and the dollar/real-rate transmission " "logic. Max 80 words. Be specific." ) SYNTH_PROMPT = ( "You are the chief macro strategist. Given the regime hypothesis " "and the four desk theses, produce a single Slack-ready trade " "brief in this exact format:\n\n" "*REGIME:* <tag>\n" "*HYPOTHESIS:* <one sentence>\n" "*RATES:* <thesis>\n" "*FX:* <thesis>\n" "*EQUITIES:* <thesis>\n" "*COMMODITIES:* <thesis>\n" "*CONVICTION:* <LOW|MEDIUM|HIGH>\n\n" "Then call post_slack_alert with channel='#macro-desk' and the " "brief as text. Do not editorialize across desks — preserve each " "thesis verbatim." ) def build_release_swarm(release_id: str, release_ts: str) -> dict: return { "name": f"Macro-Release-Reaction-{release_id}-{release_ts}", "description": ( "Scheduled reaction engine. Reasoning hypothesis fans out " "to four asset-class desks, then a synthesizer posts to Slack." ), "max_loops": 1, "task": ( f"Macro release {release_id} crossed at {release_ts} ET. " f"Run the full reaction pipeline: fetch the print, compute " f"the regime hypothesis, branch into asset desks, synthesize, " f"and post the brief to Slack." ), "agents": [ HYPOTHESIS_AGENT, { "agent_name": "RatesStrategist", "description": "Rates desk thesis.", "system_prompt": RATES_PROMPT, "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 1500, "temperature": 0.3, "tools_list_dictionary": [FETCH_MARKET_SNAPSHOT], }, { "agent_name": "FXStrategist", "description": "FX desk thesis.", "system_prompt": FX_PROMPT, "model_name": "xai/grok-4", "max_loops": 1, "max_tokens": 1500, "temperature": 0.3, "tools_list_dictionary": [FETCH_MARKET_SNAPSHOT], }, { "agent_name": "EquityStrategist", "description": "Equity desk thesis.", "system_prompt": EQUITY_PROMPT, "model_name": "claude-sonnet-4-5", "max_loops": 1, "max_tokens": 1500, "temperature": 0.3, "tools_list_dictionary": [FETCH_MARKET_SNAPSHOT], }, { "agent_name": "CommodityStrategist", "description": "Commodities desk thesis.", "system_prompt": COMMODITY_PROMPT, "model_name": "gpt-4.1-mini", "max_loops": 1, "max_tokens": 1500, "temperature": 0.3, "tools_list_dictionary": [FETCH_MARKET_SNAPSHOT], }, { "agent_name": "ThesisSynthesizer", "description": "Synthesizes the four desks into one Slack brief.", "system_prompt": SYNTH_PROMPT, "model_name": "claude-sonnet-4-5", "max_loops": 1, "max_tokens": 2000, "temperature": 0.2, "tools_list_dictionary": [POST_SLACK_ALERT], }, ], "edges": [ {"source": "HypothesisReasoner", "target": "RatesStrategist"}, {"source": "HypothesisReasoner", "target": "FXStrategist"}, {"source": "HypothesisReasoner", "target": "EquityStrategist"}, {"source": "HypothesisReasoner", "target": "CommodityStrategist"}, {"source": "RatesStrategist", "target": "ThesisSynthesizer"}, {"source": "FXStrategist", "target": "ThesisSynthesizer"}, {"source": "EquityStrategist", "target": "ThesisSynthesizer"}, {"source": "CommodityStrategist", "target": "ThesisSynthesizer"}, ], "entry_points": ["HypothesisReasoner"], "end_points": ["ThesisSynthesizer"], "auto_compile": True, } def fire_release_swarm(release_id: str, release_ts: str) -> dict: payload = build_release_swarm(release_id, release_ts) response = requests.post( f"{BASE_URL}/v1/graph-workflow/completions", headers=headers, json=payload, timeout=90, ) response.raise_for_status() return response.json() ``` Note the edge shape: one fan-out from the reasoner into four desks, one fan-in from the four desks into the synthesizer. The graph compiler runs the four desks in true parallel — total wall clock is `max(desk_latency) + synth`, not their sum. ## Step 5: Schedule Around the Economic Calendar The scheduler reads a forward calendar of release timestamps and arms a fire-exactly-on-the-minute trigger. The release is parsed within five seconds of the print; the swarm runs and posts to Slack inside thirty. ```python theme={null} RELEASE_CALENDAR = [ {"release_id": "CPI", "ts_et": "2026-06-12T08:30:00"}, {"release_id": "NFP", "ts_et": "2026-06-06T08:30:00"}, {"release_id": "FOMC", "ts_et": "2026-06-18T14:00:00"}, # ... ~50 events per year ] def schedule_release(release_id: str, ts_et_str: str) -> None: """Sleep until the release minute, then fire immediately.""" release_ts = ET.localize(datetime.fromisoformat(ts_et_str)) now_et = datetime.now(ET) wait_seconds = (release_ts - now_et).total_seconds() if wait_seconds < 0: print(f"Skipping {release_id} — already crossed.") return # Wake up 2 seconds before the release to be hot sleep_until = wait_seconds - 2 if sleep_until > 0: print(f"Sleeping {sleep_until:.0f}s until {release_id} at {ts_et_str} ET") time.sleep(sleep_until) # Poll tight until the release timestamp crosses while datetime.now(ET) < release_ts: time.sleep(0.1) print(f"FIRE {release_id} at {datetime.now(ET).isoformat()}") t0 = time.time() result = fire_release_swarm(release_id, ts_et_str) elapsed = time.time() - t0 cost = result.get("usage", {}).get("token_cost", 0) print(f"{release_id} done in {elapsed:.1f}s — cost ${cost:.2f}") # Run the whole calendar as a long-lived process if __name__ == "__main__": for event in RELEASE_CALENDAR: schedule_release(event["release_id"], event["ts_et"]) ``` In production you would run this under a process supervisor (systemd, k8s, supervisord) with an external watchdog that re-arms missed releases. For the truly latency-sensitive prints (CPI, NFP, FOMC) you also pre-warm the API with a no-op ping at T-30s so the connection is established and the keys are cached. ## Step 6: Latency Budget | Stage | Target | What runs | | ------------------------------- | ------------ | ---------------------------------------------- | | Data fetch (BLS/FRED/consensus) | \~3s | `HypothesisReasoner` tool calls in parallel | | Hypothesis reasoning | \~12s | Opus 4.8 with `reasoning_effort: "high"` | | Asset desks (parallel) | \~10s | Slowest of Rates / FX / Equities / Commodities | | Synthesizer + Slack post | \~5s | Sonnet 4.5 + `post_slack_alert` | | **End-to-end** | **\~30-40s** | **Comfortably under the 60s target** | The hard ceiling is the reasoning step — that is where the deliberation budget goes, and the only knob to tighten it further is dropping `reasoning_effort` to `"medium"` (\~6s) at the cost of regime hypothesis quality. For CPI and FOMC, do not drop it. For lower-stakes prints (Empire Manufacturing, consumer confidence) the medium setting is fine. ## Real Cost vs. Macro Desk | Approach | Cost per event | Annual (\~50 events) | Calibrated regime hypothesis? | | ----------------------------------------------- | ------------------- | ------------------------------------ | ------------------------------------------------------------- | | Macro strategist (fully loaded \$400k) | — | \$400,000 | Yes — but one human, one chain of thought, prone to anchoring | | In-house orchestration (engineers + LLM glue) | \~\$5 per event | \~\$250 plus \~\$300k/yr engineering | Maybe — depends on glue quality | | **Reaction engine (Opus high + GraphWorkflow)** | **\~\$8 per event** | **\~\$400 per year** | **Yes — and replayable, audited, deterministic** | The math is the giveaway. A single macro strategist costs roughly **a thousand times** what this engine costs to run for the same \~50 events per year. The strategist still has the job — but their work is now reviewing the engine's brief and overriding it on judgement calls, instead of trying to compute four asset reactions from scratch in 90 seconds. That is the right division of labor. <Warning> This engine is not a license to trade unattended. The Slack brief is decision support — a human on the desk approves before any execution. Compliance also requires the `job_id` of every release reaction to be persisted alongside the trade ticket for audit. Both of those drop out naturally from this architecture: one `job_id` per event, one Slack post per event, one human signoff per trade. </Warning> ## Next Steps * [Reasoning Agents for Hard Analytical Problems](/docs/examples/examples/reasoning-agents-tutorial) — the full primer on `reasoning_effort`, `self-consistency`, and when each shape is the right one * [Build an AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) — the slower, scheduled overnight cousin of this engine for the watchlist * [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) — the production DAG patterns this engine is built on (fan-out, fan-in, retries, conditional gating) # Majority Voting Example Source: https://docs.swarms.ai/docs/examples/examples/majority-voting Build a multi-agent code review board with MajorityVoting ## Automated Code Review Board This example demonstrates how to set up a panel of specialist reviewers who independently evaluate code and vote on whether it's production-ready using MajorityVoting — perfect for quality gates, approval workflows, and multi-expert decision-making. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define the Review Board Create an odd number of reviewers — each with a distinct focus area — so votes always produce a clear majority: ```python theme={null} def run_code_review(code: str, context: str = "") -> dict: """Run a multi-agent code review with majority voting.""" swarm_config = { "name": "Code Review Board", "description": "Multi-agent code review with majority voting", "swarm_type": "MajorityVoting", "task": f"""Review this code and vote on whether it is production-ready:\n\n{code}\n\n{f'Context: {context}' if context else ''}\n\nVote APPROVE if the code is production-ready. Vote REJECT if it needs changes. Explain your reasoning.""", "agents": [ { "agent_name": "Security Reviewer", "description": "Reviews code for security vulnerabilities", "system_prompt": """You are a security-focused code reviewer. Analyze code for: 1. Input validation and sanitization 2. Type safety and injection risks 3. Edge cases that could lead to security issues 4. Proper error handling for security-sensitive operations Vote APPROVE if the code is secure. Vote REJECT if there are security concerns. Always start your response with your vote.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Performance Reviewer", "description": "Reviews code for performance and efficiency", "system_prompt": """You are a performance-focused code reviewer. Analyze code for: 1. Algorithmic efficiency and time complexity 2. Memory usage and potential leaks 3. Unnecessary computations or redundant operations 4. Scalability concerns Vote APPROVE if the code is performant. Vote REJECT if there are performance concerns. Always start your response with your vote.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Best Practices Reviewer", "description": "Reviews code for adherence to best practices", "system_prompt": """You are a code quality reviewer focused on best practices. Check for: 1. Type hints and docstrings 2. Proper error handling 3. Naming conventions and readability 4. SOLID principles and clean code patterns Vote APPROVE if it follows best practices. Vote REJECT if it needs improvement. Always start your response with your vote.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Testing Reviewer", "description": "Reviews code for testability and edge cases", "system_prompt": """You are a testing-focused code reviewer. Evaluate: 1. Edge case handling (nulls, negatives, overflow, empty inputs) 2. Boundary conditions and off-by-one errors 3. Testability of the code structure 4. Missing validation that tests would catch Vote APPROVE if edge cases are well-covered. Vote REJECT if cases are missed. Always start your response with your vote.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Architecture Reviewer", "description": "Reviews code for design and maintainability", "system_prompt": """You are an architecture-focused code reviewer. Evaluate: 1. Separation of concerns and single responsibility 2. Extensibility and maintainability 3. Hardcoded values vs configurable parameters 4. Function design and API ergonomics Vote APPROVE if well-designed. Vote REJECT if architectural improvements are needed. Always start your response with your vote.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 4: Run the Code Review ```python theme={null} # Code to review code = """ def calculate_discount(price, discount_percent, is_member): if is_member: discount_percent += 10 final_price = price - (price * discount_percent / 100) if final_price < 0: final_price = 0 return round(final_price, 2) """ # Run the review board result = run_code_review(code, context="Pricing module for e-commerce checkout") # Display each reviewer's vote and reasoning for output in result.get("output", []): role = output["role"] content = output["content"] # Skip the user input echo if role == "user": continue print(f"\n{'='*60}") print(f"{role}") print(f"{'='*60}") if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:600] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` ============================================================ Security Reviewer ============================================================ Vote: APPROVE The function performs basic arithmetic with no external I/O, database queries, or user-facing output — limiting the attack surface. The negative price guard prevents negative total exploits. However, there is no input type validation — passing a string for price would raise a runtime TypeError rather than a clear error message... ============================================================ Best Practices Reviewer ============================================================ REJECT The function needs several improvements: 1. Type Hints: No type annotations for parameters or return value. Should be: def calculate_discount(price: float, discount_percent: float, is_member: bool) -> float: 2. Docstring: Missing documentation explaining parameters, return value, and behavior. 3. Magic Numbers: The 10% member bonus is hardcoded. Should be a constant or parameter... ============================================================ Performance Reviewer ============================================================ REJECT While the function is O(1) and uses minimal memory, it has code quality issues that affect production readiness: 1. No input validation — negative discount_percent would increase the price rather than decrease it 2. No type checking — non-numeric inputs cause unclear errors 3. Missing docstring for maintainability... ============================================================ Testing Reviewer ============================================================ REJECT Several edge cases are not handled: 1. Negative price: Not validated — a negative price has no real-world meaning 2. Negative discount: Could increase price unexpectedly 3. Discount > 100%: Only caught after calculation via the floor check, not validated upfront 4. Non-numeric inputs: No type checking... ============================================================ Architecture Reviewer ============================================================ REJECT Architectural concerns: 1. Separation of Concerns: The function mixes discount calculation with membership logic. The 10% bonus should be handled upstream or via a strategy pattern. 2. Magic Numbers: The hardcoded 10 violates the open/closed principle — adding new membership tiers requires modifying the function. 3. Extensibility: No way to support different discount types (percentage, fixed amount, tiered) without rewriting... ============================================================ Consensus-Agent ============================================================ FINAL VERDICT: REJECT (4-1) The code review board has voted to REJECT this function for production use. Four of five reviewers identified significant issues: Key Issues (by priority): 1. No input validation (security, testing, performance) 2. Missing type hints and docstring (best practices) 3. Hardcoded magic number for member discount (architecture) 4. Poor separation of concerns (architecture) The Security Reviewer approved based on the limited attack surface, but acknowledged the lack of type validation. Recommendation: Address input validation, add type hints and docstring, extract the member bonus as a configurable constant, and add proper error handling before merging... Total cost: $0.1151 ``` ### Step 5: Review Multiple Code Snippets Use MajorityVoting as a quality gate in a CI-like pipeline: ```python theme={null} def batch_code_review(snippets: dict[str, str]) -> None: """Review multiple code snippets and summarize results.""" print(f"Reviewing {len(snippets)} code snippets...\n") for name, code in snippets.items(): result = run_code_review(code) outputs = result.get("output", []) # Get the consensus agent's final verdict consensus = "" for output in outputs: if output["role"] == "Consensus-Agent": content = output["content"] if isinstance(content, list): content = ' '.join(str(item) for item in content) consensus = str(content) break # Determine result approved = "approve" in consensus.lower()[:100] status = "APPROVED" if approved else "REJECTED" print(f" {name}: {status}") print(f" {consensus[:150]}...") print() # Review multiple functions snippets = { "validate_email": ''' def validate_email(email: str) -> bool: """Validate email format.""" import re pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' return bool(re.match(pattern, email)) ''', "divide_numbers": ''' def divide(a, b): return a / b ''', } batch_code_review(snippets) ``` <Note> MajorityVoting runs all agents independently in parallel, then a Consensus-Agent tallies the votes and synthesizes the reasoning into a final verdict. Use an odd number of agents (3, 5, 7) to guarantee a clear majority and avoid ties. Each agent should have a distinct evaluation focus and clear voting instructions in their system prompt. </Note> # Build an Agent CLI over MCP (TypeScript) Source: https://docs.swarms.ai/docs/examples/examples/mcp-agent-typescript Go from an empty folder to a working multi-turn agent CLI in about ten minutes, talking to the hosted Swarms MCP server at mcp.swarms.world with the official TypeScript SDK. ## What This Tutorial Builds A command-line tool you can run as `npm start "your question here"` that: * Connects to the hosted Swarms MCP server — nothing to install or self-host * Runs a single agent and prints its answer * Carries conversation history across turns so follow-up questions work * Reports the exact cost of every call * Fails loudly and correctly instead of printing `undefined` ## Why MCP Instead of Plain HTTP You can call `https://api.swarms.world/v1/agent/completions` with `fetch` and it works. MCP earns its place when the same client also needs to *discover* what is available, or when the client is itself an agent choosing tools at runtime. Over MCP you get a typed tool list, a uniform result envelope, and one transport that any other MCP-aware program can reuse. The credential also lives on the transport rather than in your request bodies, so it never travels as a tool argument. <Note> **No installation required.** The Swarms MCP server is hosted at `https://mcp.swarms.world/mcp`. You need an API key from the [API Keys page](https://swarms.world/platform/api-keys) and nothing else. </Note> ## Step 1: Create the Project ```bash theme={null} mkdir swarms-agent-cli && cd swarms-agent-cli npm init -y npm install @modelcontextprotocol/sdk npm install -D tsx typescript ``` Set `"type": "module"` in `package.json` so top-level `await` works, and add a start script: ```json theme={null} { "name": "swarms-agent-cli", "type": "module", "scripts": { "start": "tsx agent.ts" } } ``` Export your key: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Connect to the Server Create `client.ts`. This is the only file that knows about transports and credentials. ```typescript theme={null} import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const SERVER_URL = "https://mcp.swarms.world/mcp"; export async function connect(): Promise<Client> { const apiKey = process.env.SWARMS_API_KEY; if (!apiKey) { throw new Error("SWARMS_API_KEY is not set"); } // The credential rides on the transport as a header. It is never a tool // argument, so the model driving these tools never sees it. const transport = new StreamableHTTPClientTransport(new URL(SERVER_URL), { requestInit: { headers: { "x-api-key": apiKey } }, }); const client = new Client({ name: "swarms-agent-cli", version: "1.0.0" }); await client.connect(transport); return client; } ``` The server is **stateless** — there is no session id to store or replay. Each connection is independent, so you can open one per process and close it when you are done. ## Step 3: See What the Server Offers Before writing any tool call, look at what is actually there. Create `list.ts`: ```typescript theme={null} import { connect } from "./client.js"; const client = await connect(); const { tools } = await client.listTools(); console.log(`${tools.length} tools available:\n`); for (const tool of tools) { console.log(` ${tool.name}`); } await client.close(); ``` ```bash theme={null} npx tsx list.ts ``` You should see 23 tools. The one this tutorial uses is `run_agent_v1_agent_completions_post`, which maps to `POST /v1/agent/completions`. <Note> `listTools` works without a valid key — discovery is open. Only `callTool` requires credentials. That is useful when you want an agent to inspect the tool surface before you commit a key to it. </Note> ## Step 4: Your First Agent Call Create `agent.ts`: ```typescript theme={null} import { connect } from "./client.js"; const client = await connect(); const result = await client.callTool({ name: "run_agent_v1_agent_completions_post", arguments: { agent_config: { agent_name: "explainer", description: "Explains technical concepts concisely and correctly.", system_prompt: "You are a precise technical explainer. Prefer short paragraphs " + "and concrete examples over abstractions. Never pad your answer.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }, task: "Explain the CAP theorem in three bullets.", }, }); console.log(result.structuredContent); await client.close(); ``` ```bash theme={null} npx tsx agent.ts ``` ## Step 5: Read the Result Correctly Every tool result carries the same envelope, and getting this right is most of what separates a working client from a flaky one. | Field | What it is | Use it? | | ------------------- | --------------------------------------------- | -------------------------------- | | `structuredContent` | The upstream JSON, already parsed | **Yes** | | `content[0].text` | A status line followed by pretty-printed JSON | Only for logs and error messages | | `isError` | `true` when the upstream call failed | **Always check first** | The critical detail: **an upstream failure does not throw.** A 429, a 422, an expired key — all of these come back as a normal result with `isError: true`. If you skip the check and read `structuredContent`, you get `undefined` and a confusing crash three lines later. ```typescript theme={null} if (result.isError) { // content[0].text holds the upstream status line and body. throw new Error(`Swarms call failed: ${result.content[0].text}`); } const payload = result.structuredContent as any; console.log(payload.outputs[0].content); console.log(`cost: $${payload.usage.total_cost}`); ``` The agent response shape: ```json theme={null} { "job_id": "agent-b0abf28…", "success": true, "name": "explainer", "outputs": [ { "role": "explainer", "content": "…", "timestamp": "…", "message_id": "…" } ], "usage": { "input_tokens": 7, "output_tokens": 62, "total_tokens": 69, "total_cost": 0.001192 } } ``` `outputs` is an array because an agent running `max_loops` greater than one produces one entry per loop. The last entry is the final answer. ## Step 6: Add Conversation History A single call is stateless. To make follow-ups work, pass the prior turns back as `history` — an array of `{ role, content }` objects. ```typescript theme={null} type Turn = { role: string; content: string }; async function ask( client: Client, task: string, history: Turn[], ): Promise<{ answer: string; cost: number }> { const result = await client.callTool({ name: "run_agent_v1_agent_completions_post", arguments: { agent_config: { agent_name: "explainer", system_prompt: "You are a precise technical explainer.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }, task, // Omit history entirely on the first turn rather than sending []. ...(history.length > 0 ? { history } : {}), }, }); if (result.isError) { throw new Error(`Swarms call failed: ${result.content[0].text}`); } const payload = result.structuredContent as any; const answer = payload.outputs[payload.outputs.length - 1].content; return { answer, cost: payload.usage.total_cost }; } ``` Then thread the history through your loop: ```typescript theme={null} const history: Turn[] = []; for (const question of ["What is the CAP theorem?", "Which do most SQL databases pick?"]) { const { answer } = await ask(client, question, history); console.log(`\nQ: ${question}\nA: ${answer}`); history.push({ role: "user", content: question }); history.push({ role: "assistant", content: answer }); } ``` The second question — "which do most SQL databases pick?" — only makes sense because the first turn is in history. ## Step 7: Handle Timeouts Agents with high `max_loops`, or swarms, routinely run longer than a default HTTP timeout. Raise it explicitly on the call: ```typescript theme={null} const result = await client.callTool( { name: "run_agent_v1_agent_completions_post", arguments: { /* … */ } }, undefined, { timeout: 300_000 }, // 5 minutes ); ``` <Warning> Do not retry a failed completion blindly. Agent calls are billed, and a timeout on the client side does not necessarily mean the server abandoned the work. Retry on connection errors; investigate on timeouts. </Warning> ## Step 8: The Complete CLI `agent.ts`, in full: ```typescript theme={null} import type { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { connect } from "./client.js"; type Turn = { role: string; content: string }; const AGENT_CONFIG = { agent_name: "explainer", description: "Explains technical concepts concisely and correctly.", system_prompt: "You are a precise technical explainer. Prefer short paragraphs and " + "concrete examples over abstractions. Never pad your answer.", model_name: "gpt-4o-mini", max_loops: 1, max_tokens: 2000, }; async function ask(client: Client, task: string, history: Turn[]) { const result = await client.callTool( { name: "run_agent_v1_agent_completions_post", arguments: { agent_config: AGENT_CONFIG, task, ...(history.length > 0 ? { history } : {}), }, }, undefined, { timeout: 300_000 }, ); if (result.isError) { throw new Error(`Swarms call failed: ${(result.content as any)[0].text}`); } const payload = result.structuredContent as any; return { answer: payload.outputs[payload.outputs.length - 1].content as string, cost: payload.usage.total_cost as number, }; } const question = process.argv.slice(2).join(" "); if (!question) { console.error('usage: npm start "your question"'); process.exit(1); } const client = await connect(); let spent = 0; try { const first = await ask(client, question, []); console.log(first.answer); spent += first.cost; const history: Turn[] = [ { role: "user", content: question }, { role: "assistant", content: first.answer }, ]; const followUp = "In one sentence, what is the most common mistake people make about this?"; const second = await ask(client, followUp, history); console.log(`\n--- ${followUp} ---\n${second.answer}`); spent += second.cost; } finally { console.log(`\ntotal cost: $${spent.toFixed(6)}`); await client.close(); } ``` Run it: ```bash theme={null} npm start "Explain the CAP theorem in three bullets." ``` ## Common Errors | Symptom | Cause | Fix | | ------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------- | | `Cannot read properties of undefined` | Read `structuredContent` without checking `isError` | Check `isError` first | | Message about supplying `x-api-key` | Key missing from the transport headers | Set it in `requestInit.headers`, not in `arguments` | | Upstream `422` in the error text | `agent_config` field name or type is wrong | Compare against `inputSchema` from `listTools` | | Request hangs then fails | Default timeout too short for the run | Pass `{ timeout: 300_000 }` | | `403` on batch tools | Batch endpoints are premium-only | [Upgrade your account](https://swarms.world/platform/account) | ## Next Steps * [Build a Multi-Agent Research Tool in Rust over MCP](/docs/examples/examples/mcp-swarm-rust) — when one agent is not enough * [Run a Batch Pipeline over MCP (Python)](/docs/examples/examples/mcp-batch-pipeline-python) — for thousands of records * [Swarms API MCP Server](/docs/documentation/clients/swarms-api-mcp) — the full tool reference # Run a Batch Pipeline over MCP (Python) Source: https://docs.swarms.ai/docs/examples/examples/mcp-batch-pipeline-python Classify thousands of records through the hosted Swarms MCP server — chunk to the 50-item cap, fan the chunks out concurrently over one session, survive partial failures, and account for every cent. ## What This Tutorial Builds A pipeline that takes a list of support tickets and returns a triage decision for each one — severity, category, suggested team — by pushing them through `run_agent_batch_v1_agent_batch_completions_post` on the hosted MCP server. It covers the parts that only show up at scale: * Chunking a large input list to the endpoint's hard **50-item cap** * Running chunks concurrently over a **single** MCP session * Surviving partial failures without losing the whole run * Parsing model output that is *supposed* to be JSON and sometimes is not * Accounting for cost per record, not per run <Warning> **Batch endpoints are premium-only.** `/v1/agent/batch/completions` is restricted to Pro, Ultra, and Premium subscribers, and a free-tier key gets a `403`. [Upgrade your account](https://swarms.world/platform/account) to run this tutorial. </Warning> ## Why Batch Instead of a Loop Calling the single-agent tool once per record works and is easy to reason about. It also pays connection and scheduling overhead on every one of ten thousand records, and it serializes work the server would happily parallelize. The batch tool takes up to 50 completions in one call and fans them out server-side. Your job shrinks to two things: chunk correctly, and run a bounded number of chunks at once. ## Step 1: Setup ```bash theme={null} pip install mcp export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Open One Session, Reuse It The single most common performance mistake is opening a new MCP session per chunk. Connect once and pass the session down. ```python theme={null} import os import httpx from mcp import ClientSession from mcp.client.streamable_http import streamable_http_client SERVER = "https://mcp.swarms.world/mcp" def http_client() -> httpx.AsyncClient: api_key = os.environ.get("SWARMS_API_KEY") if not api_key: raise SystemExit("SWARMS_API_KEY is not set") # The credential is a transport header, never a tool argument. return httpx.AsyncClient( headers={"x-api-key": api_key}, timeout=600 ) ``` The 600-second timeout is deliberate. A 50-item batch of real work routinely runs for minutes, and the default `httpx` timeout will cut it off mid-flight. ## Step 3: Define the Agent Once Every record in the batch reuses the same `agent_config`. Only the `task` changes. ```python theme={null} TRIAGE_AGENT = { "agent_name": "ticket-triage", "description": "Triages inbound customer support tickets.", "system_prompt": ( "You are a support operations lead. Given a ticket, respond with " "strict JSON and nothing else: " '{"severity": "P0"|"P1"|"P2"|"P3", ' '"category": "billing"|"bug"|"howto"|"outage"|"other", ' '"team": string, "reason": "one sentence"}' ), "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 300, "temperature": 0.2, } ``` Low `max_tokens` and low `temperature` are what make batch economics work. You are asking for a classification, not an essay — cap the output so one verbose row cannot triple the bill. ## Step 4: Chunk to the Cap The batch tool accepts **at most 50 items**. Exceeding it is a validation error, not a silent truncation. ```python theme={null} BATCH_LIMIT = 50 def to_completion(ticket: dict) -> dict: return { "agent_config": TRIAGE_AGENT, "task": ( f"Ticket {ticket['id']} from a {ticket['tier']} customer.\n" f"Subject: {ticket['subject']}\n" f"Body: {ticket['body']}" ), } def chunk(items: list, size: int = BATCH_LIMIT) -> list[list]: return [items[i : i + size] for i in range(0, len(items), size)] ``` ## Step 5: Run One Chunk One chunk is one tool call. Check `isError` before touching the payload — an upstream `403`, `429`, or `422` arrives as a *result*, not an exception. ```python theme={null} async def run_chunk(session: ClientSession, tickets: list[dict]) -> dict: result = await session.call_tool( "run_agent_batch_v1_agent_batch_completions_post", {"body": [to_completion(t) for t in tickets]}, ) if result.is_error: raise RuntimeError(result.content[0].text) return result.structured_content ``` The batch response shape: ```json theme={null} { "batch_id": "agent-batch-57088ba…", "total_requests": 50, "results": [ { "job_id": "agent-80e25c9…", "success": true, "name": "ticket-triage", "outputs": [{ "role": "ticket-triage", "content": "{\"severity\": …}", "timestamp": "…" }], "usage": { "total_tokens": 71, "total_cost": 0.001277 } } ], "execution_time": 3.45, "timestamp": "…" } ``` `results` is positional — `results[i]` corresponds to `body[i]`. That is what lets you rejoin the model's answer to your original record. ## Step 6: Fan Out, but Bounded Running every chunk at once will hit your rate limit. A semaphore keeps a fixed number in flight. ```python theme={null} import asyncio CONCURRENCY = 5 async def run_all( session: ClientSession, tickets: list[dict] ) -> list[dict]: chunks = chunk(tickets) limiter = asyncio.Semaphore(CONCURRENCY) async def guarded(batch: list[dict]) -> dict | BaseException: async with limiter: try: return await run_chunk(session, batch) except Exception as exc: # one bad chunk must not sink the run return exc return await asyncio.gather(*(guarded(c) for c in chunks)) ``` Returning the exception rather than raising is the important part. In a 10,000-record run, one chunk failing on a transient `429` should cost you 50 records to retry — not the other 9,950. <Note> Start at `CONCURRENCY = 5` and raise it while watching `get_rate_limits_v1_rate_limits_get`. The right number depends on your tier, not on your machine. </Note> ## Step 7: Rejoin and Parse The agent was told to return JSON. Sometimes it will return JSON wrapped in a code fence, or a sentence of preamble. Handle that instead of trusting it. ````python theme={null} import json def parse_decision(raw: str) -> dict | None: text = raw.strip() if text.startswith("```"): # strip a ```json … ``` fence text = text.split("\n", 1)[-1].rsplit("```", 1)[0].strip() try: return json.loads(text) except json.JSONDecodeError: return None def rejoin(tickets: list[dict], responses: list) -> tuple[list, list]: triaged, review_queue = [], [] index = 0 for response in responses: batch = tickets[index : index + BATCH_LIMIT] index += BATCH_LIMIT if isinstance(response, BaseException): review_queue.extend( {"ticket": t, "error": str(response)} for t in batch ) continue for ticket, item in zip(batch, response["results"]): if not item.get("success"): review_queue.append({"ticket": ticket, "error": "agent failed"}) continue decision = parse_decision(item["outputs"][-1]["content"]) if decision is None: review_queue.append( {"ticket": ticket, "error": "unparseable output"} ) continue triaged.append({**ticket, **decision}) return triaged, review_queue ```` Every record ends up in exactly one of two lists. Nothing is silently dropped — that is the property you want when the input is a customer backlog. ## Step 8: Account for the Cost Each result carries its own `usage`, so the true cost of the run is a sum, not an estimate. ```python theme={null} def total_cost(responses: list) -> float: return sum( item["usage"]["total_cost"] for response in responses if not isinstance(response, BaseException) for item in response["results"] if item.get("success") ) ``` ## Step 9: The Complete Pipeline ````python theme={null} import asyncio import json import os import httpx from mcp import ClientSession from mcp.client.streamable_http import streamable_http_client SERVER = "https://mcp.swarms.world/mcp" BATCH_LIMIT = 50 CONCURRENCY = 5 TRIAGE_AGENT = { "agent_name": "ticket-triage", "description": "Triages inbound customer support tickets.", "system_prompt": ( "You are a support operations lead. Given a ticket, respond with " "strict JSON and nothing else: " '{"severity": "P0"|"P1"|"P2"|"P3", ' '"category": "billing"|"bug"|"howto"|"outage"|"other", ' '"team": string, "reason": "one sentence"}' ), "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 300, "temperature": 0.2, } def build_tickets(count: int) -> list[dict]: subjects = [ ("Charged twice this month", "premium"), ("Dashboard returns 500 on load", "free"), ("How do I rotate my API key?", "pro"), ("Everything is down for our whole org", "enterprise"), ] tickets = [] for i in range(count): subject, tier = subjects[i % len(subjects)] tickets.append( { "id": f"T{i:05d}", "tier": tier, "subject": subject, "body": f"{subject}. Please advise. (case {i})", } ) return tickets def to_completion(ticket: dict) -> dict: return { "agent_config": TRIAGE_AGENT, "task": ( f"Ticket {ticket['id']} from a {ticket['tier']} customer.\n" f"Subject: {ticket['subject']}\n" f"Body: {ticket['body']}" ), } def chunk(items: list, size: int = BATCH_LIMIT) -> list[list]: return [items[i : i + size] for i in range(0, len(items), size)] def parse_decision(raw: str) -> dict | None: text = raw.strip() if text.startswith("```"): text = text.split("\n", 1)[-1].rsplit("```", 1)[0].strip() try: return json.loads(text) except json.JSONDecodeError: return None async def run_chunk(session: ClientSession, tickets: list[dict]) -> dict: result = await session.call_tool( "run_agent_batch_v1_agent_batch_completions_post", {"body": [to_completion(t) for t in tickets]}, ) if result.is_error: raise RuntimeError(result.content[0].text) return result.structured_content async def run_all(session: ClientSession, tickets: list[dict]) -> list: limiter = asyncio.Semaphore(CONCURRENCY) async def guarded(batch: list[dict]): async with limiter: try: return await run_chunk(session, batch) except Exception as exc: return exc return await asyncio.gather(*(guarded(c) for c in chunk(tickets))) def rejoin(tickets: list[dict], responses: list) -> tuple[list, list]: triaged, review_queue = [], [] index = 0 for response in responses: batch = tickets[index : index + BATCH_LIMIT] index += BATCH_LIMIT if isinstance(response, BaseException): review_queue.extend( {"ticket": t, "error": str(response)} for t in batch ) continue for ticket, item in zip(batch, response["results"]): if not item.get("success"): review_queue.append({"ticket": ticket, "error": "agent failed"}) continue decision = parse_decision(item["outputs"][-1]["content"]) if decision is None: review_queue.append( {"ticket": ticket, "error": "unparseable output"} ) continue triaged.append({**ticket, **decision}) return triaged, review_queue def total_cost(responses: list) -> float: return sum( item["usage"]["total_cost"] for response in responses if not isinstance(response, BaseException) for item in response["results"] if item.get("success") ) async def main() -> None: api_key = os.environ.get("SWARMS_API_KEY") if not api_key: raise SystemExit("SWARMS_API_KEY is not set") tickets = build_tickets(120) print(f"triaging {len(tickets)} tickets " f"in {len(chunk(tickets))} chunks\n") async with ( httpx.AsyncClient( headers={"x-api-key": api_key}, timeout=600 ) as http, streamable_http_client(SERVER, http_client=http) as (read, write), ClientSession(read, write) as session, ): await session.initialize() responses = await run_all(session, tickets) triaged, review_queue = rejoin(tickets, responses) by_severity: dict[str, int] = {} for row in triaged: by_severity[row["severity"]] = by_severity.get(row["severity"], 0) + 1 print(f"triaged: {len(triaged)}") print(f"needs review: {len(review_queue)}") for severity in sorted(by_severity): print(f" {severity}: {by_severity[severity]}") cost = total_cost(responses) print(f"\ntotal cost: ${cost:.4f}") if triaged: print(f"cost per ticket: ${cost / len(triaged):.6f}") if __name__ == "__main__": asyncio.run(main()) ```` ## Scaling Past 10,000 Records Nothing in the code above changes — only the numbers do. | Records | Chunks | At `CONCURRENCY = 5` | | ------- | ------ | -------------------- | | 120 | 3 | one wave | | 1,000 | 20 | 4 waves | | 10,000 | 200 | 40 waves | The knobs, in the order worth turning: 1. **`CONCURRENCY`** — the real throughput lever. Raise it until `get_rate_limits_v1_rate_limits_get` says you are close to your ceiling. 2. **`max_tokens`** — the real cost lever. A classification needs 300 tokens, not 16,000. 3. **`model_name`** — try the cheapest model that holds accuracy on a 100-record sample before running 10,000. <Warning> Validate on a small sample first. Run 100 records, read the output by hand, and confirm the JSON contract holds before you spend on the full backlog. A prompt that produces prose instead of JSON costs the same as one that works. </Warning> ## Common Errors | Symptom | Cause | Fix | | ------------------------------------- | ------------------------------------------- | -------------------------------------------------------------- | | Upstream `403` | Batch endpoints are premium-only | [Upgrade your account](https://swarms.world/platform/account) | | Upstream `422` mentioning list length | Chunk larger than 50 | Keep `BATCH_LIMIT` at 50 | | `429` on some chunks | `CONCURRENCY` too high for your tier | Lower it; retry just the failed chunks | | `ReadTimeout` | Default `httpx` timeout too short | Pass `timeout=600` to `AsyncClient` | | Many "unparseable output" rows | The model is not honoring the JSON contract | Tighten the system prompt, lower `temperature` | | Results matched to the wrong record | Assumed order is not guaranteed | `results[i]` matches `body[i]` — rejoin positionally, as above | ## Next Steps * [Build an Agent CLI over MCP (TypeScript)](/docs/examples/examples/mcp-agent-typescript) — the single-record version * [Build a Multi-Agent Research Tool in Rust over MCP](/docs/examples/examples/mcp-swarm-rust) — when one agent per record is not enough * [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) — a whole swarm per record * [Rate Limits](/docs/documentation/resources/ratelimits) — what to check before raising concurrency # MCP Integration Source: https://docs.swarms.ai/docs/examples/examples/mcp-integration Integrate Model Context Protocol servers for external data access and tools The Swarms API supports Model Context Protocol (MCP) integration, allowing agents to connect to external servers and access additional tools, data sources, and capabilities beyond the base API. <Info> MCP integration enables agents to access external databases, APIs, and tools through standardized server connections. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Data Analyst with MCP", "description": "Data analyst with access to external databases", "system_prompt": "You are a data analyst with access to external data sources through MCP.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.5, "mcp_url": "https://github.com/mcp" # Your MCP server URL }, "task": "Query the customer database and provide insights on recent sales trends." } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) result = response.json() print(result['outputs']) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const payload = { agent_config: { agent_name: "Financial Analyst", description: "Financial analyst with real-time market data access", system_prompt: "You are a financial analyst with access to real-time market data through MCP.", model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.3, mcp_url: "https://your-mcp-server.com/financial-data" }, task: "Analyze the current market trends for tech stocks and provide investment recommendations." }; fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { console.log("Analysis Results:", data.outputs); console.log("Token Usage:", data.usage); }) .catch(error => console.error('Error:', error)); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Data Analyst with MCP", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.5, "mcp_url": "http://localhost:8001/sse" }, "task": "Query the customer database and provide insights on recent sales trends." }' ``` </Tab> </Tabs> ## MCP Server Setup ### Local MCP Server ```python theme={null} # Example MCP server setup (server.py) from mcp import Server import asyncio app = Server("data-server") @app.list_tools() async def list_tools(): return [ { "name": "query_database", "description": "Query the customer database", "inputSchema": { "type": "object", "properties": { "query": {"type": "string"} }, "required": ["query"] } } ] @app.call_tool() async def call_tool(name, arguments): if name == "query_database": # Your database query logic here return {"result": "Query executed successfully"} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8001) ``` ### Running the MCP Server ```bash theme={null} # Install MCP dependencies pip install mcp-server # Run your MCP server python server.py ``` ## Advanced MCP Configuration ### Multiple MCP Connections ```python theme={null} payload = { "agent_config": { "agent_name": "Multi-Source Analyst", "description": "Analyst with access to multiple data sources", "system_prompt": "You have access to multiple MCP servers for comprehensive analysis.", "model_name": "gpt-4.1", "max_tokens": 8192, "mcp_configs": { "connections": [ { "url": "http://localhost:8001/sse" }, { "url": "http://localhost:8002/sse" } ] } }, "task": "Combine customer data with market trends to provide business insights." } ``` ### Single MCP with Advanced Config ```python theme={null} payload = { "agent_config": { "agent_name": "Advanced MCP Agent", "description": "Agent with advanced MCP configuration", "system_prompt": "You are connected to an MCP server with advanced capabilities.", "model_name": "gpt-4.1", "max_tokens": 4096, "mcp_config": { "url": "http://localhost:8001/sse", "timeout": 30, "authorization_token": "your-token", "transport": "streamable_http" } }, "task": "Perform complex data analysis using the MCP server tools." } ``` ## Use Cases ### Database Integration ```python theme={null} payload = { "agent_config": { "agent_name": "Database Analyst", "description": "SQL database integration specialist", "system_prompt": "You can query databases and analyze structured data.", "model_name": "gpt-4.1", "mcp_url": "http://localhost:8001/sse" }, "task": "Analyze sales data from the past quarter and identify top performing products." } ``` ### Financial Data Access ```python theme={null} payload = { "agent_config": { "agent_name": "Financial Analyst", "description": "Real-time financial data analysis", "system_prompt": "You analyze financial markets and provide investment insights.", "model_name": "gpt-4.1", "mcp_url": "https://api.marketdata.com/mcp" }, "task": "Analyze the current stock prices and provide buy/sell recommendations." } ``` ### API Integration ```python theme={null} payload = { "agent_config": { "agent_name": "API Integrator", "description": "External API integration specialist", "system_prompt": "You can call external APIs and integrate third-party services.", "model_name": "gpt-4.1", "mcp_url": "http://localhost:8003/sse" }, "task": "Fetch weather data and provide travel recommendations based on current conditions." } ``` ## Best Practices 1. **Server Reliability**: Ensure your MCP server is stable and handles errors gracefully 2. **Authentication**: Implement proper authentication for MCP server access 3. **Timeout Handling**: Set appropriate timeouts for long-running operations 4. **Error Handling**: Handle MCP connection failures and retry logic 5. **Resource Management**: Monitor resource usage and implement rate limiting 6. **Documentation**: Document available MCP tools and their capabilities ## Cost Considerations * **MCP Calls**: \$0.10 per request that sets `mcp_url` (charged once per request, not per tool call) * **Token Usage**: Additional tokens for MCP tool interactions * **Server Costs**: Costs associated with running your MCP server ## Error Handling ```python theme={null} try: response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60 ) if response.status_code == 200: result = response.json() print("MCP Results:", result['outputs']) else: print(f"MCP Error: {response.status_code} - {response.text}") except requests.exceptions.Timeout: print("MCP request timed out") except requests.exceptions.ConnectionError: print("Failed to connect to MCP server") except Exception as e: print(f"MCP integration error: {e}") ``` ## Troubleshooting ### Common Issues 1. **Connection Refused**: Ensure MCP server is running and accessible 2. **Authentication Failed**: Check API keys and authentication headers 3. **Timeout Errors**: Increase timeout values for complex operations 4. **Tool Not Found**: Verify tool names match server implementation 5. **Rate Limiting**: Implement backoff strategies for rate-limited endpoints ### Debug Mode Enable debug logging on your client to troubleshoot MCP issues: ```python theme={null} import logging logging.basicConfig(level=logging.DEBUG) ``` # Build a Multi-Agent Research Tool in Rust over MCP Source: https://docs.swarms.ai/docs/examples/examples/mcp-swarm-rust Use the official rmcp crate to drive a Swarms multi-agent workflow from Rust — connect over Streamable HTTP, run a SequentialWorkflow, and deserialize the result into real types with serde. ## What This Tutorial Builds A `cargo run` binary that sends one research question to a **swarm of three agents** — a researcher, a skeptic, and an editor — and prints each agent's contribution plus the run's cost and wall time. Along the way: * Connecting to the hosted MCP server with [`rmcp`](https://crates.io/crates/rmcp), the official Rust MCP SDK * Sending credentials as transport headers rather than tool arguments * Deserializing the tool result into typed structs with `serde`, not `Value` indexing * Choosing a swarm architecture for the shape of your problem ## Why a Swarm Instead of One Agent A single agent with a long prompt tends to agree with itself. Asking one model to "research this, then critique your own research, then edit it" produces a fluent answer that has never actually been challenged. A swarm makes the critique a *separate* call with a *separate* system prompt and no stake in the earlier output. `SequentialWorkflow` passes each agent's output to the next, so the skeptic sees the research and the editor sees both. <Note> **No installation required.** The Swarms MCP server is hosted at `https://mcp.swarms.world/mcp`. You need an API key from the [API Keys page](https://swarms.world/platform/api-keys). </Note> ## Step 1: Create the Project ```bash theme={null} cargo new swarms-research cd swarms-research ``` `Cargo.toml`: ```toml theme={null} [package] name = "swarms-research" version = "0.1.0" edition = "2021" [dependencies] rmcp = { version = "3.1", features = [ "client", "reqwest", "transport-streamable-http-client-reqwest", ] } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } serde = { version = "1", features = ["derive"] } serde_json = "1" ``` The three `rmcp` features matter: | Feature | Why | | ------------------------------------------ | ----------------------------------------------------------------- | | `client` | The client half of the SDK — without it there is no `serve` | | `transport-streamable-http-client-reqwest` | Streamable HTTP client transport, which is what the server speaks | | `reqwest` | Pulls in `reqwest` with `rustls` for TLS | ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Connect `rmcp` builds a transport from a config, then `serve` turns it into a running client. The unit type `()` is a valid client handler when you only make requests and do not handle server-initiated calls. ```rust theme={null} use std::collections::HashMap; use rmcp::transport::{ streamable_http_client::StreamableHttpClientTransportConfig, StreamableHttpClientTransport, }; use rmcp::ServiceExt; const SERVER_URL: &str = "https://mcp.swarms.world/mcp"; async fn connect() -> Result<impl std::ops::Deref, Box<dyn std::error::Error>> { let api_key = std::env::var("SWARMS_API_KEY")?; // The credential is a transport header, never a tool argument. let mut headers = HashMap::new(); headers.insert("x-api-key".parse()?, api_key.parse()?); let transport = StreamableHttpClientTransport::from_config( StreamableHttpClientTransportConfig::with_uri(SERVER_URL) .custom_headers(headers), ); Ok(().serve(transport).await?) } ``` In the finished program below this is inlined into `main` — the signature of a running `rmcp` service is awkward to name, and inlining avoids fighting it. <Note> `custom_headers` takes a `HashMap<HeaderName, HeaderValue>`. Both sides come from `.parse()`, which is why the `?` operators are there — a malformed header name is a runtime error, not a compile error. </Note> ## Step 3: Define the Result Types This is where Rust pays off. Instead of indexing into a `Value` and hoping, describe the response once and let `serde` enforce it. ```rust theme={null} use serde::Deserialize; #[derive(Debug, Deserialize)] struct SwarmResult { job_id: String, status: String, swarm_type: String, output: Vec<Message>, number_of_agents: u32, execution_time: f64, usage: Usage, } #[derive(Debug, Deserialize)] struct Message { role: String, content: String, } #[derive(Debug, Deserialize)] struct Usage { total_tokens: u64, billing_info: BillingInfo, } #[derive(Debug, Deserialize)] struct BillingInfo { total_cost: f64, } ``` Fields you do not declare are ignored, so you can start with the four you care about and grow the struct as you need more. ## Step 4: Design the Swarm Three agents, each with a job the next one cannot do for itself: ```rust theme={null} use serde_json::{json, Value}; fn swarm_arguments(question: &str) -> Value { json!({ "name": "research-desk", "description": "Research a question, challenge the findings, then publish.", "swarm_type": "SequentialWorkflow", "task": question, "max_loops": 1, "agents": [ { "agent_name": "researcher", "system_prompt": "Gather the relevant facts and lay them out plainly. \ Cite what is well established and mark what is contested.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, { "agent_name": "skeptic", "system_prompt": "You are reviewing the research above. Attack its weakest \ claims. Name every assumption presented as fact. Be specific \ and do not soften your criticism.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, { "agent_name": "editor", "system_prompt": "You have the research and the critique. Write the final \ answer, keeping only claims that survived. State remaining \ uncertainty explicitly.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 } ] }) } ``` `SequentialWorkflow` runs these in array order and feeds each output forward. Other architectures change that wiring: | `swarm_type` | Wiring | Use when | | -------------------- | ---------------------------------------- | ----------------------------------------------------- | | `SequentialWorkflow` | Each output feeds the next | Stages build on each other — research, critique, edit | | `ConcurrentWorkflow` | All agents see the task, run in parallel | Independent perspectives on the same input | | `MajorityVoting` | Parallel, then a vote | You want the most-agreed answer, not a synthesis | | `DebateWithJudge` | Agents argue, a judge rules | The question is genuinely contested | | `HierarchicalSwarm` | A director delegates to workers | The task needs decomposition first | | `auto` | The server picks | You do not want to choose | The full list is in [Available Architectures](/docs/documentation/multi-agent/available-architectures). ## Step 5: Call the Tool `CallToolRequestParams` is `#[non_exhaustive]`, so build it with `new` plus `with_arguments` rather than a struct literal. ```rust theme={null} use rmcp::model::CallToolRequestParams; let result = client .call_tool( CallToolRequestParams::new("run_swarm_v1_swarm_completions_post") .with_arguments(swarm_arguments(&question).as_object().cloned().unwrap()), ) .await?; ``` Then check for failure **before** touching the payload. An upstream error — a bad key, a 429, a 422 — arrives as `is_error: Some(true)` with the detail in `content`, not as an `Err`: ```rust theme={null} if result.is_error.unwrap_or(false) { return Err(format!("swarm call failed: {:?}", result.content).into()); } let payload = result .structured_content .ok_or("no structured content in result")?; let swarm: SwarmResult = serde_json::from_value(payload)?; ``` ## Step 6: The Complete Program `src/main.rs`: ```rust theme={null} use std::collections::HashMap; use rmcp::model::CallToolRequestParams; use rmcp::transport::{ streamable_http_client::StreamableHttpClientTransportConfig, StreamableHttpClientTransport, }; use rmcp::ServiceExt; use serde::Deserialize; use serde_json::json; const SERVER_URL: &str = "https://mcp.swarms.world/mcp"; #[derive(Debug, Deserialize)] struct SwarmResult { job_id: String, status: String, swarm_type: String, output: Vec<Message>, number_of_agents: u32, execution_time: f64, usage: Usage, } #[derive(Debug, Deserialize)] struct Message { role: String, content: String, } #[derive(Debug, Deserialize)] struct Usage { total_tokens: u64, billing_info: BillingInfo, } #[derive(Debug, Deserialize)] struct BillingInfo { total_cost: f64, } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let question: String = std::env::args().skip(1).collect::<Vec<_>>().join(" "); let question = if question.is_empty() { "What are the real limits of vector databases for long-term agent memory?".to_string() } else { question }; let api_key = std::env::var("SWARMS_API_KEY") .map_err(|_| "SWARMS_API_KEY is not set")?; // The credential is a transport header, never a tool argument. let mut headers = HashMap::new(); headers.insert("x-api-key".parse()?, api_key.parse()?); let transport = StreamableHttpClientTransport::from_config( StreamableHttpClientTransportConfig::with_uri(SERVER_URL).custom_headers(headers), ); let client = ().serve(transport).await?; let arguments = json!({ "name": "research-desk", "description": "Research a question, challenge the findings, then publish.", "swarm_type": "SequentialWorkflow", "task": question, "max_loops": 1, "agents": [ { "agent_name": "researcher", "system_prompt": "Gather the relevant facts and lay them out plainly. Cite what is well established and mark what is contested.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, { "agent_name": "skeptic", "system_prompt": "You are reviewing the research above. Attack its weakest claims. Name every assumption presented as fact. Be specific and do not soften your criticism.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 }, { "agent_name": "editor", "system_prompt": "You have the research and the critique. Write the final answer, keeping only claims that survived. State remaining uncertainty explicitly.", "model_name": "gpt-4o-mini", "max_loops": 1, "max_tokens": 2000 } ] }); println!("running swarm on: {question}\n"); let result = client .call_tool( CallToolRequestParams::new("run_swarm_v1_swarm_completions_post") .with_arguments(arguments.as_object().cloned().unwrap()), ) .await?; // Upstream failures arrive as a result with is_error set, not as an Err. if result.is_error.unwrap_or(false) { return Err(format!("swarm call failed: {:?}", result.content).into()); } let payload = result .structured_content .ok_or("no structured content in result")?; let swarm: SwarmResult = serde_json::from_value(payload)?; for message in &swarm.output { println!("=== {} ===", message.role); println!("{}\n", message.content); } println!("---"); println!("job: {}", swarm.job_id); println!("status: {}", swarm.status); println!("type: {}", swarm.swarm_type); println!("agents: {}", swarm.number_of_agents); println!("elapsed: {:.1}s", swarm.execution_time); println!("tokens: {}", swarm.usage.total_tokens); println!("cost: ${:.6}", swarm.usage.billing_info.total_cost); client.cancel().await?; Ok(()) } ``` Run it: ```bash theme={null} cargo run -- "What are the real limits of vector databases for agent memory?" ``` The first entry in `output` has role `User` and echoes your task — the agents follow after it, in execution order. ## Step 7: Discovering Tools at Runtime `list_tools` takes an `Option<PaginatedRequestParams>`, so `Default::default()` gives you the unpaginated call: ```rust theme={null} let tools = client.list_tools(Default::default()).await?; for tool in tools.tools { println!("{}", tool.name); } ``` ## Common Errors | Symptom | Cause | Fix | | ------------------------------------- | ----------------------------------------------- | ------------------------------------------------------- | | `cannot create non-exhaustive struct` | Struct literal for `CallToolRequestParams` | Use `CallToolRequestParams::new(..).with_arguments(..)` | | `missing field` from `serde_json` | A struct field the response does not carry | Make it `Option<T>` or drop it | | Message about supplying `x-api-key` | Header not on the transport | Set it via `custom_headers` | | `no structured content in result` | The call errored upstream | Check `is_error` first — the reason is in `content` | | Swarm runs for minutes | Normal for three agents with large `max_tokens` | Lower `max_tokens`, or use `ConcurrentWorkflow` | <Warning> Every swarm run is billed per agent plus tokens. A three-agent `SequentialWorkflow` costs roughly three times a single agent call on the same task. Read `usage.billing_info.total_cost` on every response rather than estimating. </Warning> ## Next Steps * [Build an Agent CLI over MCP (TypeScript)](/docs/examples/examples/mcp-agent-typescript) — the single-agent version * [Run a Batch Pipeline over MCP (Python)](/docs/examples/examples/mcp-batch-pipeline-python) — many records at once * [Available Architectures](/docs/documentation/multi-agent/available-architectures) — every `swarm_type` explained # Production Medical Research Pipeline Source: https://docs.swarms.ai/docs/examples/examples/medical-research-pipeline A four-agent SequentialWorkflow that turns a clinical research question into an evidence-based, audit-ready recommendation memo for ~$1, then fans the same pipeline across an overnight queue via /v1/swarm/batch/completions. ## What This Example Shows * A `SequentialWorkflow` chaining four clinical-research specialist agents: Literature Reviewer, Clinical Trial Analyst, Evidence Synthesizer, and Recommendations Editor * How to reuse a rigorous clinical-research system prompt (`MED_SYS_PROMPT`) as the basis for every agent's voice * A concrete worked example on a stage III pancreatic adenocarcinoma evidence question * How to fan the same pipeline across an overnight queue of research questions via `/v1/swarm/batch/completions` for the 50% night-mode discount * A regulated-industry-friendly artifact: per-agent audit trail in the swarm log, plus an explicit reviewer checklist for the licensed clinician <Warning> This pipeline is for **research and development only**. It is **not** for direct clinical decision-making without licensed-physician review. Output must be reviewed and signed off by a qualified clinician before it informs any patient care, formulary decision, or published material. </Warning> ## Why This Matters A pharma medical-affairs analyst, a payer policy researcher, or a hospital evidence-review team is paid \$200-\$400 per hour to produce exactly this artifact: a structured memo that answers "what does the evidence say, and what should we do?" for a single clinical question. The job typically runs 4-8 billable hours per memo — \$800 to \$3,200 of loaded labor — plus a one-to-two week turnaround that bottlenecks downstream decisions like formulary inclusion, payer policy updates, and KOL outreach. This pipeline produces the same shape of first draft in roughly a minute for about a dollar. The licensed reviewer keeps the role they actually add value in: signing off. ## Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Step 2: Install Dependencies ```bash theme={null} pip install requests python-dotenv ``` ## Step 3: Configure the Client ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 4: Anchor the Pipeline on a Rigorous System Prompt Every agent in this pipeline is a variation on one rigorous clinical-research persona. Define it once and reuse it across the chain so the voice, evidence standards, and citation discipline stay consistent end to end. ```python theme={null} MED_SYS_PROMPT = """ You are an Advanced Clinical Research Specialist with extensive expertise in medical research methodology, clinical trial analysis, and evidence-based medicine. Your primary responsibilities include: 1. LITERATURE ANALYSIS: Conduct comprehensive reviews of peer-reviewed medical literature, clinical trial data, and research publications. Critically evaluate study methodologies, statistical significance, sample sizes, and potential biases. 2. TREATMENT EVALUATION: Analyze the efficacy, safety, and comparative effectiveness of medical treatments and interventions. Assess patient outcomes, adverse events, and long-term implications of therapeutic approaches. 3. CLINICAL TRIAL ASSESSMENT: Review and interpret clinical trial results, including Phase I-IV studies, randomized controlled trials, meta-analyses, and systematic reviews. Identify strengths, limitations, and clinical applicability of research findings. 4. EVIDENCE SYNTHESIS: Synthesize complex medical data from multiple sources to provide clear, actionable insights. Distinguish between correlation and causation, and evaluate the quality and reliability of evidence. 5. RECOMMENDATION FORMULATION: Develop evidence-based recommendations for clinical practice, considering patient populations, comorbidities, contraindications, and real-world applicability. 6. RESEARCH GAP IDENTIFICATION: Identify areas requiring further investigation and suggest directions for future research. Your analysis must be rigorous, objective, and grounded in scientific evidence. Present findings in a structured format that includes: executive summary, methodology assessment, key findings, statistical analysis, clinical implications, limitations, and recommendations. Maintain scientific accuracy while ensuring accessibility for both medical professionals and stakeholders. Always cite sources appropriately and acknowledge the limitations of available evidence. """ ``` ## Step 5: Define the Clinical Research Question A concrete, defensible question is the most important input. Vague prompts get vague memos. The example below targets stage III pancreatic cancer — an active area of evidence and a real question medical-affairs and payer teams ask every week. ```python theme={null} CLINICAL_QUESTION = ( "What are the latest evidence-based treatments for stage III pancreatic " "adenocarcinoma in adults with ECOG performance status 0-1? Cover " "(1) the current standard-of-care chemotherapy and chemoradiation " "regimens (FOLFIRINOX, gemcitabine + nab-paclitaxel, neoadjuvant " "approaches), (2) any approved or late-phase targeted therapies and " "immunotherapies relevant to this stage, (3) the strength of the " "underlying evidence (RCTs, meta-analyses, NCCN/ESMO guidelines), and " "(4) actively recruiting clinical trials worth flagging." ) ``` ## Step 6: Define the Four-Agent Pipeline Each agent owns one phase of the memo and inherits the shared `MED_SYS_PROMPT` plus a lane-specific addendum. The `SequentialWorkflow` passes the previous agent's output as upstream context, so the Trial Evaluator critiques what the Research Specialist surfaced, the Treatment Recommender builds on that critique, and the Risk/Compliance Reviewer audits the whole chain. ```python theme={null} payload = { "name": "Medical Research Sequential Pipeline", "description": ( "Clinical Research Specialist -> Clinical Trial Analyst -> " "Evidence Synthesizer -> Recommendations Editor. Produces an " "audit-ready first-draft research memo for licensed-clinician review." ), "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": CLINICAL_QUESTION, "agents": [ { "agent_name": "Clinical Research Specialist", "description": "Performs evidence retrieval and literature synthesis.", "system_prompt": ( MED_SYS_PROMPT + "\n\nYour specific role in this pipeline is the LITERATURE " "REVIEW stage. For the given clinical question, produce a " "structured literature synthesis: (1) the disease context " "and unmet need, (2) the landmark trials and meta-analyses " "relevant to the question with study design, n, primary " "endpoint, and headline result, (3) the current major " "guideline positions (NCCN, ESMO, ASCO as applicable), and " "(4) the open scientific questions. Cite sources by name. " "Do not make treatment recommendations yet — that is the " "next agent's job." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Clinical Trial Analyst", "description": "Critically appraises trial quality and statistical validity.", "system_prompt": ( MED_SYS_PROMPT + "\n\nYour specific role is the CLINICAL TRIAL ANALYSIS " "stage. Given the Research Specialist's literature synthesis, " "critically appraise each trial: risk of bias, population " "generalizability, primary vs. secondary endpoint validity, " "effect size and confidence intervals, number needed to " "treat, and discordances across trials or meta-analyses. " "Flag any actively recruiting trials. Rate the overall " "strength of evidence (high / moderate / low / very low) " "using GRADE-style reasoning and explain your rating." ), "model_name": "anthropic/claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 6144, }, { "agent_name": "Evidence Synthesizer", "description": "Translates evidence into a guideline-eligible treatment approach.", "system_prompt": ( MED_SYS_PROMPT + "\n\nYour specific role is the EVIDENCE SYNTHESIS stage. " "Using the Research Specialist's synthesis and the Clinical " "Trial Analyst's appraisal, produce: (1) the recommended " "patient population (inclusion criteria, key comorbidities " "to consider), (2) the suggested regimen with sequencing " "and dose intensity considerations, (3) monitoring " "parameters and follow-up cadence, (4) anticipated benefit " "framed in median OS / PFS, absolute risk reduction, and " "NNT where reported, and (5) where the evidence is weakest " "and the recommendation is conditional. Be specific and " "clinical." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Recommendations Editor", "description": "Final editorial pass with explicit limitations and reviewer checklist.", "system_prompt": ( MED_SYS_PROMPT + "\n\nYour specific role is the FINAL EDITORIAL stage. " "Convert the upstream synthesis into a clean, structured " "research memo with these sections: (1) Question, " "(2) Executive Summary (5-7 bullets), (3) Treatment " "Landscape with explicit evidence grades, (4) Key Trials " "Table, (5) Open Questions and Research Gaps, " "(6) Explicit Limitations of This Analysis, and (7) A " "Reviewer Checklist for the licensed physician who will " "sign off. Also audit the upstream draft for over-claiming, " "off-label statements, and populations excluded from the " "underlying trials. Conclude the memo with a single " "'Approved for physician review' or 'Revision required' " "verdict, plus an enumerated list of required revisions " "if any." ), "model_name": "anthropic/claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 6144, }, ], } ``` <Note> The Clinical Research Specialist and Evidence Synthesizer run on `gpt-4.1` at low temperature (0.3) for repeatable structured output. The Clinical Trial Analyst and Recommendations Editor run on `anthropic/claude-opus-4-8` — Opus reasoning is well-suited to critical appraisal and final editorial review. The `temperature` field is intentionally omitted for the Opus 4.8 agents (the API drops it before forwarding to Anthropic; see the [Claude Opus 4.8 example](/docs/examples/examples/claude-opus-4-8)). </Note> ## Step 7: Run the Pipeline ```python theme={null} response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) response.raise_for_status() result = response.json() for output in result.get("output", []): print("=" * 70) print(output["role"]) print("=" * 70) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)) print() cost = result["usage"]["billing_info"]["total_cost"] elapsed = result["execution_time"] print(f"Total cost: ${cost:.4f}") print(f"Elapsed: {elapsed:.1f}s") ``` ## Step 8: Verify the Editor Verdict and Persist the Audit Trail The Recommendations Editor is the last agent in the chain, so its output is the last entry in `result["output"]`. Gate downstream delivery on its verdict, then write the full per-agent log to disk for the audit record. ```python theme={null} final = result["output"][-1] final_text = final["content"] if isinstance(final_text, list): final_text = " ".join(str(c) for c in final_text) if "Approved for physician review" in final_text: print("Memo cleared compliance. Routing to clinician inbox.") else: print("Memo flagged. Do NOT route. Reviewer notes:") print(final_text) ``` Persist the full per-agent log so the credentialed reviewer has a defensible audit record before they sign off: ```python theme={null} import datetime audit_record = { "job_id": result.get("job_id"), "timestamp_utc": datetime.datetime.utcnow().isoformat() + "Z", "question": CLINICAL_QUESTION, "pipeline": "Production Medical Research Pipeline", "per_agent_output": result.get("output", []), "usage": result.get("usage", {}), "execution_time_seconds": result.get("execution_time"), } filename = f"memo_{result.get('job_id', 'unknown')}.json" with open(filename, "w") as f: json.dump(audit_record, f, indent=2) print(f"Audit record saved to {filename}") ``` That JSON is your evidence that the memo was produced from a specific question, in a specific agent order, at a specific moment. Pair it with the reviewer's sign-off and you have a defensible record. ## Step 9: Overnight Queue with `/v1/swarm/batch/completions` Medical-affairs and policy teams rarely have just one open question. The same pipeline can be fanned across a queue of questions in a single API call using `/v1/swarm/batch/completions`. Scheduled overnight (8 PM to 6 AM Pacific) the platform also applies a **50% night-time discount** on token costs (see `calculate_swarm_cost` in `api/swarm_completions.py`). ```python theme={null} def build_payload(question: str) -> dict: """Clone the pipeline payload, swap in a new research question.""" body = json.loads(json.dumps(payload)) # deep copy body["task"] = question return body research_queue = [ ( "What are the latest evidence-based treatments for stage III " "pancreatic adenocarcinoma in adults with ECOG 0-1?" ), ( "What does the current evidence say about GLP-1 receptor agonists " "for cardiovascular risk reduction in non-diabetic patients with " "obesity?" ), ( "Summarize the evidence for CAR-T therapy in relapsed/refractory " "diffuse large B-cell lymphoma, including comparative effectiveness " "versus autologous stem cell transplant." ), ( "What is the current standard of care and emerging evidence for " "minimal residual disease (MRD) monitoring in multiple myeloma?" ), ] batch_payload = [build_payload(q) for q in research_queue] batch_response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=batch_payload, timeout=1200, ) batch_results = batch_response.json() for idx, swarm_result in enumerate(batch_results): job_id = swarm_result.get("job_id", f"job-{idx}") cost = ( swarm_result.get("usage", {}) .get("billing_info", {}) .get("total_cost", 0) ) print(f"[{idx}] job_id={job_id} cost=${cost:.4f}") with open(f"memo_{job_id}.json", "w") as f: json.dump(swarm_result, f, indent=2) ``` <Info> The batch endpoint accepts a JSON array where every item is a full `SwarmSpec` — identical to the body you pass to `/v1/swarm/completions`. Items run in parallel server-side, so a 4-question queue does not take 4x the wall-clock time. Pair this with a scheduled job that fires after 8 PM Pacific and the entire queue runs on the night-time discount. </Info> ## Per-Query Cost vs. Consultant Time A medical-research analyst inside pharma medical affairs, a payer policy team, or a hospital evidence-review office bills \$200-\$400 per hour and typically spends 4-8 hours per memo of this shape. The same first draft from this pipeline lands in roughly a minute for about a dollar, even before the night-mode discount. | Method | Time per memo | Cost per memo | | ------------------------------------------------------------------- | ----------------------- | ----------------------- | | Medical research analyst at \$200/hr × 4 hrs | 4 hours | \$800 | | Medical research analyst at \$400/hr × 8 hrs | 8 hours | \$3,200 | | **This pipeline (single query)** | \~1 minute | **\~\$1** | | **This pipeline (4-question overnight batch, night-mode discount)** | \~1-2 minutes wall time | **a few dollars total** | | **This pipeline + 30 min physician sign-off** | \~32 minutes | **\~\$150** | The pipeline does not replace the clinician — it relocates them from drafting to reviewing, which is both faster and higher-leverage. ## Adapting the Pipeline Replace the question and tighten the prompts to retarget: | Domain | Agent 1 | Agent 2 | Agent 3 | Agent 4 | | ---------------------------- | ---------------------- | -------------------------- | --------------------- | ------------------------ | | **Drug-class deep dive** | Literature Synthesizer | Trial Evaluator | Treatment Recommender | Compliance Reviewer | | **Pharmacovigilance review** | Signal Detector | Causal Assessor | Mitigation Designer | Regulatory Reviewer | | **Formulary decision memo** | Evidence Aggregator | Cost-Effectiveness Analyst | Formulary Recommender | P\&T Compliance Reviewer | | **CME content drafting** | Topic Researcher | Evidence Critic | Module Writer | Accreditation Reviewer | The pipeline shape, billing, and response schema stay identical. ## Common Pitfalls <AccordionGroup> <Accordion title="The Recommendations Editor always says 'Revision required'"> Tighten the Evidence Synthesizer's prompt to explicitly cite the evidence-strength rating from the Clinical Trial Analyst and to avoid universal claims ("all patients with stage III pancreatic cancer should...") in favor of population-scoped claims ("guideline-eligible patients with ECOG 0-1 and adequate organ function..."). The editor is doing its job — your upstream prompt is over-claiming. </Accordion> <Accordion title="The output is generic and not 'clinical-sounding'"> Increase `max_tokens` on the Clinical Research Specialist and Evidence Synthesizer to 8192, and add domain anchors to the question ("for a 68-year-old with borderline-resectable stage III pancreatic adenocarcinoma, ECOG 1, CA 19-9 320..."). Sequential pipelines amplify upstream specificity — vague input compounds into vague output. </Accordion> <Accordion title="Where does this fit in our compliance program?"> Pair this pipeline with the [Swarm Logs](/docs/examples/examples/swarm-logs) endpoint to maintain a full audit trail of every prompt, every agent output, and every reviewer verdict tied to your API key. Most regulated medical-affairs programs require that trail; the API gives it to you for free. </Accordion> </AccordionGroup> ## Next Steps * See the [Clinical Case Conference](/docs/examples/examples/clinical-case-conference) example for the hierarchical (parallel-specialist) variant of this pattern * See [Hospital Team](/docs/examples/examples/hospital-team) for a discharge-planning-focused multi-agent workflow * Read the [Production Readiness Checklist](/docs/guides/guides/production-readiness-checklist) before shipping this pipeline to a regulated production environment # Build a Usage Dashboard Source: https://docs.swarms.ai/docs/examples/examples/metrics-summary Quick start tutorial for the /v1/metrics/summary endpoint The `/v1/metrics/summary` endpoint gives you all of your core usage metrics in a single call — perfect for powering a dashboard. In this tutorial you'll fetch your metrics and print a small summary. ## Step 1 — Get your API key Create an API key in your dashboard: `https://swarms.world/platform/api-keys` ## Step 2 — Add it to .env ```bash theme={null} SWARMS_API_KEY=your-api-key-here ``` ## Step 3 — Fetch your metrics <Tabs> <Tab title="Python"> ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() BASE_URL = "https://api.swarms.world" headers = { "x-api-key": os.getenv("SWARMS_API_KEY"), "Content-Type": "application/json", } resp = requests.get( f"{BASE_URL}/v1/metrics/summary", headers=headers, ) print(resp.status_code) data = resp.json() print(json.dumps(data, indent=2)) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} require('dotenv').config(); const BASE_URL = "https://api.swarms.world"; const API_KEY = process.env.SWARMS_API_KEY; async function main() { const res = await fetch(`${BASE_URL}/v1/metrics/summary`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' } }); console.log(res.status); const data = await res.json(); console.log(JSON.stringify(data, null, 2)); } main().catch(console.error); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X GET "https://api.swarms.world/v1/metrics/summary" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" ``` </Tab> </Tabs> ## Step 4 — Render the dashboard tiles Pull the headline numbers out of the response and compute a success rate. These are the values you'd wire into dashboard cards. <Tabs> <Tab title="Python"> ```python theme={null} total = data["total_completion_calls"] success = data["successful_completions"] success_rate = (success / total * 100) if total else 0.0 print("── Usage Summary ─────────────") print(f"Unique agents used: {data['unique_agents']}") print(f"Total completions: {total}") print(f"Successful completions: {success} ({success_rate:.1f}%)") print(f"Completions (24h): {data['completions_last_24h']}") print(f"Completions (7d): {data['completions_last_7d']}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const total = data.total_completion_calls; const success = data.successful_completions; const successRate = total ? (success / total * 100).toFixed(1) : "0.0"; console.log("── Usage Summary ─────────────"); console.log(`Unique agents used: ${data.unique_agents}`); console.log(`Total completions: ${total}`); console.log(`Successful completions: ${success} (${successRate}%)`); console.log(`Completions (24h): ${data.completions_last_24h}`); console.log(`Completions (7d): ${data.completions_last_7d}`); ``` </Tab> </Tabs> Example output: ```text theme={null} ── Usage Summary ───────────── Unique agents used: 80 Total completions: 25583 Successful completions: 13516 (52.8%) Completions (24h): 2 Completions (7d): 1151 ``` ## What you get back | Field | What it's for | | ------------------------ | ----------------------------------------------------- | | `unique_agents` | How many distinct agents you've used | | `total_completion_calls` | Lifetime completion calls | | `successful_completions` | Completions that finished with status `success` | | `completions_last_24h` | Volume in the last day (for deltas / spike detection) | | `completions_last_7d` | Volume in the last week | <Note> For a full field reference and use cases, see the [User Metrics Summary](/docs/documentation/capabilities/metrics_summary) capability page. </Note> # Mixture of Agents Example Source: https://docs.swarms.ai/docs/examples/examples/mixture-of-agents Build an investment due diligence system with MixtureOfAgents ## Startup Due Diligence System This example demonstrates how to get multiple expert perspectives on the same topic using MixtureOfAgents - perfect for comprehensive analysis requiring diverse viewpoints. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define Expert Panel Create multiple experts who will all analyze the same startup from different perspectives: ```python theme={null} def run_due_diligence(startup_info: str) -> dict: """Run multi-expert due diligence on a startup.""" swarm_config = { "name": "Startup Due Diligence", "description": "Multi-expert investment analysis", "swarm_type": "MixtureOfAgents", "task": f"""Conduct due diligence analysis for investment consideration: {startup_info} Provide your specialized analysis and a score from 1-10.""", "agents": [ { "agent_name": "Technical Expert", "description": "Evaluates technology and engineering", "system_prompt": """You are a Technical Due Diligence Expert. Analyze: 1. Tech stack (scalability, modernity) 2. Engineering team strength 3. IP and technical moat 4. Technical risks Provide a TECHNICAL SCORE (1-10) with justification.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Financial Analyst", "description": "Assesses financials and valuation", "system_prompt": """You are a Financial Due Diligence Expert. Analyze: 1. Revenue and growth trajectory 2. Unit economics (CAC, LTV, margins) 3. Burn rate and runway 4. Valuation reasonableness Provide a FINANCIAL SCORE (1-10) with justification.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Market Strategist", "description": "Evaluates market opportunity", "system_prompt": """You are a Market Strategy Expert. Analyze: 1. TAM/SAM and market growth 2. Competitive landscape 3. Competitive moat 4. Go-to-market strategy Provide a MARKET SCORE (1-10) with justification.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Legal Advisor", "description": "Reviews legal and compliance", "system_prompt": """You are a Legal Due Diligence Expert. Analyze: 1. Corporate structure 2. Regulatory compliance 3. IP ownership 4. Legal risks Provide a LEGAL SCORE (1-10) with justification.""", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 3: Run Due Diligence Analysis ```python theme={null} import re # Startup to analyze startup = """ COMPANY: DataFlow AI INDUSTRY: Enterprise SaaS / AI DESCRIPTION: AI-powered data integration platform that automates ETL pipelines using natural language. DETAILS: - Founded: 2023 - Stage: Seed - Funding Sought: $4M - Team Size: 12 - Revenue: $180K ARR, growing 25% MoM - Tech Stack: Python, Kubernetes, PostgreSQL, GPT-4 API - Metrics: 45 paying customers, 92% retention, $4K ACV - Competitors: Fivetran, Airbyte, dbt, Matillion """ # Run analysis result = run_due_diligence(startup) # Extract scores and display def extract_score(content): match = re.search(r'score[:\s]+(\d+)/10', content.lower()) return int(match.group(1)) if match else None scores = {} for output in result.get("output", []): expert = output["role"] content = output["content"] score = extract_score(content) scores[expert] = score print(f"\n{'='*50}") print(f"{expert.upper()}" + (f" - Score: {score}/10" if score else "")) print(f"{'='*50}") print(content[:600] + "...") # Aggregate if scores: valid_scores = [s for s in scores.values() if s] avg = sum(valid_scores) / len(valid_scores) print(f"\n{'='*50}") print("AGGREGATE ASSESSMENT") print(f"{'='*50}") for expert, score in scores.items(): bar = "#" * (score or 0) + "-" * (10 - (score or 0)) print(f"{expert:20} [{bar}] {score}/10") print(f"\nOVERALL SCORE: {avg:.1f}/10") if avg >= 7: print("RECOMMENDATION: Proceed with investment") elif avg >= 5: print("RECOMMENDATION: Address concerns before proceeding") else: print("RECOMMENDATION: Pass") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` ================================================== TECHNICAL EXPERT - Score: 7/10 ================================================== TECHNICAL ANALYSIS Tech Stack Assessment: - Python + Kubernetes is a solid, scalable foundation - PostgreSQL appropriate for structured data - GPT-4 API dependency is a risk factor Strengths: - Modern cloud-native architecture - AI-first approach differentiates from legacy ETL tools Concerns: - Heavy reliance on OpenAI API (vendor lock-in, cost)... ================================================== FINANCIAL ANALYST - Score: 8/10 ================================================== FINANCIAL ANALYSIS Revenue: $180K ARR with 25% MoM growth is strong for seed stage... ================================================== AGGREGATE ASSESSMENT ================================================== Technical Expert [#######---] 7/10 Financial Analyst [########--] 8/10 Market Strategist [#######---] 7/10 Legal Advisor [######----] 6/10 OVERALL SCORE: 7.0/10 RECOMMENDATION: Proceed with investment Total cost: $0.1523 ``` <Note> MixtureOfAgents gives you multiple expert perspectives on the same input. Each expert sees identical information but analyzes through their specialized lens, revealing insights a single analyst might miss. </Note> # Available Models Source: https://docs.swarms.ai/docs/examples/examples/models-available Discover and explore all available AI models supported by the Swarms API Get a comprehensive list of all AI models available through the Swarms API. This endpoint provides information about supported models from various providers including OpenAI, Anthropic, Groq, and others. <Info> The `/v1/models/available` endpoint returns all models currently supported by the Swarms API, including their capabilities and limitations. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } def get_available_models(): """Get all available models""" response = requests.get( f"{BASE_URL}/v1/models/available", headers=headers ) if response.status_code == 200: return response.json() else: print(f"Error: {response.status_code} - {response.text}") return None # Get available models models_data = get_available_models() if models_data: print("✅ Available models retrieved successfully!") print(models_data) print(f"Model count: {models_data['count']}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getAvailableModels() { try { const response = await fetch(`${BASE_URL}/v1/models/available`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Available models retrieved successfully!"); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error('Error:', error); return null; } } // Get available models getAvailableModels(); ``` </Tab> <Tab title="cURL"> ```bash theme={null} # Get available models curl -X GET "https://api.swarms.world/v1/models/available" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" # Example response: # { # "success": true, # "count": 42, # "models": [ # "gpt-4.1", # "gpt-4.1-mini", # "gpt-4-turbo", # "claude-sonnet-4-20250514", # "claude-haiku-3.5", # "groq/llama-3.1-70b-versatile", # "openrouter/aion-labs/aion-3.0" # ] # } ``` </Tab> </Tabs> ## Understanding the Response The models endpoint returns a flat list of all available model identifiers, filtered by your subscription tier: ```json theme={null} { "success": true, "count": 42, "models": [ "gpt-4.1", "gpt-4.1-mini", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo", "claude-sonnet-4-20250514", "claude-haiku-3.5", "groq/llama-3.1-70b-versatile", "groq/llama-3.1-8b-instant" ] } ``` | Field | Type | Description | | --------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `success` | boolean | Whether the request succeeded | | `count` | integer | Number of models in the `models` list | | `models` | array of strings | Flat list of available model identifiers, filtered by your subscription tier (free tier accounts won't see premium or Groq models) | By default, this list also includes models fetched live from OpenRouter (cached for 5 minutes) and prefixed with `openrouter/` (e.g. `openrouter/aion-labs/aion-3.0`). The base catalog is precomputed and cached server-side, so this endpoint is cheap to call. ## OpenAI-Compatible Model List If you use the OpenAI SDK (or any client that discovers models via `GET /v1/models`), the same tier-filtered catalog is available in the standard OpenAI list format: <Tabs> <Tab title="Python"> ```python theme={null} from openai import OpenAI client = OpenAI( api_key=API_KEY, base_url="https://api.swarms.world/v1", ) models = client.models.list() print(f"{len(models.data)} models available") for model in models.data[:10]: print(f"{model.id} (owned_by: {model.owned_by})") ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X GET "https://api.swarms.world/v1/models" \ -H "x-api-key: your-api-key" # Example response: # { # "object": "list", # "data": [ # {"id": "gpt-4.1", "object": "model", "created": 0, "owned_by": "openai"}, # {"id": "claude-sonnet-4-20250514", "object": "model", "created": 0, "owned_by": "anthropic"} # ] # } ``` </Tab> </Tabs> Each entry has `id` (the model identifier you pass as `model_name` or `model`), `object` (always `"model"`), `created`, and `owned_by` (the resolved provider, e.g. `openai`, `anthropic`). See the [OpenAI-Compatible Endpoint](/docs/documentation/capabilities/openai-compatible) reference for using these models with the OpenAI SDK. ## Model Selection Guide ### For Text Generation <Tabs> <Tab title="Creative Tasks"> ```python theme={null} # Best for creative writing, brainstorming, content generation recommended_models = [ "gpt-4.1", # Most capable, balanced performance "claude-sonnet-4-20250514", # Excellent for creative tasks "gpt-4.1-mini" # Fast and cost-effective ] ``` </Tab> <Tab title="Analytical Tasks"> ```python theme={null} # Best for analysis, reasoning, complex problem-solving recommended_models = [ "gpt-4.1", # Superior reasoning capabilities "claude-sonnet-4-20250514", # Strong analytical performance "gpt-4-turbo" # Good balance of speed and capability ] ``` </Tab> <Tab title="Fast Responses"> ```python theme={null} # Best for quick responses, simple tasks, cost optimization recommended_models = [ "gpt-4.1-mini", # Fastest and most cost-effective "llama-3.1-8b-instant", # Very fast inference "claude-haiku-3.5" # Fast with good quality ] ``` </Tab> </Tabs> ## Model Capabilities <Tabs> <Tab title="Vision Models"> ```python theme={null} # Models that support image analysis vision_models = [ "gpt-4.1", # Best vision capabilities "gpt-4-turbo", # Good vision support "gpt-4.1-mini" # Basic vision support ] # Example: Vision-enabled agent payload = { "agent_config": { "agent_name": "Vision Analyst", "model_name": "gpt-4.1", # Vision-capable model "max_tokens": 2048 }, "task": "Describe this image in detail", "img": "https://example.com/image.jpg" } ``` </Tab> <Tab title="Streaming Models"> ```python theme={null} # Models that support streaming responses streaming_models = [ "gpt-4.1", "gpt-4.1-mini", "claude-sonnet-4-20250514", "claude-haiku-3.5" ] # Example: Streaming-enabled agent payload = { "agent_config": { "agent_name": "Streaming Writer", "model_name": "gpt-4.1", "streaming_on": True, # Enable streaming "max_tokens": 2048 }, "task": "Write a creative story" } ``` </Tab> <Tab title="Large Context Models"> ```python theme={null} # Models with large context windows large_context_models = [ "gpt-4.1", # 128k+ tokens "claude-sonnet-4-20250514", # 200k+ tokens "gpt-4-turbo", # 128k tokens ] # Example: Large document analysis payload = { "agent_config": { "agent_name": "Document Analyst", "model_name": "gpt-4.1", # Large context "max_tokens": 4096 }, "task": "Analyze this 50-page document and provide insights" } ``` </Tab> </Tabs> ## Dynamic Model Selection <Tabs> <Tab title="Python"> ```python theme={null} def select_best_model(task_type, priority="balanced"): """ Dynamically select the best model based on task type and priority Args: task_type: Type of task ("creative", "analytical", "fast", "vision") priority: Priority ("quality", "speed", "cost", "balanced") """ # Get available models first models_data = get_available_models() if not models_data or not models_data.get("success"): return "gpt-4.1-mini" # Fallback available_models = models_data.get("models", []) # Model selection logic if task_type == "creative": if priority == "quality": return "gpt-4.1" if "gpt-4.1" in available_models else "claude-sonnet-4-20250514" elif priority == "speed": return "gpt-4.1-mini" if "gpt-4.1-mini" in available_models else "claude-haiku-3.5" else: # balanced return "gpt-4.1-mini" elif task_type == "analytical": return "gpt-4.1" if "gpt-4.1" in available_models else "claude-sonnet-4-20250514" elif task_type == "fast": return "gpt-4.1-mini" if "gpt-4.1-mini" in available_models else "llama-3.1-8b-instant" elif task_type == "vision": return "gpt-4.1" if "gpt-4.1" in available_models else "gpt-4-turbo" return "gpt-4.1-mini" # Default fallback # Example usage best_model = select_best_model("creative", "quality") print(f"Selected model: {best_model}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} function selectBestModel(taskType, priority = "balanced") { // Model selection logic for JavaScript const modelPreferences = { creative: { quality: ["gpt-4.1", "claude-sonnet-4-20250514"], speed: ["gpt-4.1-mini", "claude-haiku-3.5"], balanced: ["gpt-4.1-mini"], cost: ["gpt-4.1-mini", "llama-3.1-8b-instant"] }, analytical: { quality: ["gpt-4.1", "claude-sonnet-4-20250514"], speed: ["gpt-4-turbo"], balanced: ["gpt-4.1"], cost: ["gpt-4.1-mini"] }, fast: { quality: ["gpt-4.1-mini"], speed: ["gpt-4.1-mini", "llama-3.1-8b-instant"], balanced: ["gpt-4.1-mini"], cost: ["gpt-4.1-mini", "llama-3.1-8b-instant"] }, vision: { quality: ["gpt-4.1"], speed: ["gpt-4.1-mini"], balanced: ["gpt-4.1"], cost: ["gpt-4-turbo"] } }; const candidates = modelPreferences[taskType]?.[priority] || ["gpt-4.1-mini"]; return candidates[0]; // Return first preference } // Example usage const bestModel = selectBestModel("creative", "quality"); console.log(`Selected model: ${bestModel}`); ``` </Tab> </Tabs> ## Model Performance Comparison | Model | Context Window | Best For | Speed | Cost | | -------------------------- | -------------- | --------------------------- | ------ | ------ | | `gpt-4.1` | 128k+ | Complex reasoning, vision | Medium | High | | `gpt-4.1-mini` | 128k+ | General purpose, fast tasks | Fast | Low | | `claude-sonnet-4-20250514` | 200k+ | Creative writing, analysis | Medium | High | | `claude-haiku-3.5` | 200k+ | Fast responses | Fast | Low | | `llama-3.1-70b` | 128k | Complex tasks | Medium | Medium | | `llama-3.1-8b` | 128k | Simple tasks | Fast | Low | ## Cost Optimization <Tabs> <Tab title="Python"> ```python theme={null} def optimize_model_selection(task_complexity, budget_constraint): """ Select optimal model based on task complexity and budget """ if task_complexity == "low": return "gpt-4.1-mini" if budget_constraint == "strict" else "llama-3.1-8b-instant" elif task_complexity == "medium": return "gpt-4.1-mini" if budget_constraint == "strict" else "gpt-4.1" else: # high complexity return "claude-sonnet-4-20250514" if budget_constraint == "flexible" else "gpt-4.1" # Example usage model = optimize_model_selection("high", "flexible") print(f"Optimized model: {model}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} function optimizeModelSelection(taskComplexity, budgetConstraint) { const optimizationMatrix = { low: { strict: "gpt-4.1-mini", flexible: "llama-3.1-8b-instant" }, medium: { strict: "gpt-4.1-mini", flexible: "gpt-4.1" }, high: { strict: "gpt-4.1", flexible: "claude-sonnet-4-20250514" } }; return optimizationMatrix[taskComplexity]?.[budgetConstraint] || "gpt-4.1-mini"; } // Example usage const model = optimizeModelSelection("high", "flexible"); console.log(`Optimized model: ${model}`); ``` </Tab> </Tabs> ## Error Handling <Tabs> <Tab title="Python"> ```python theme={null} def get_available_models_with_fallback(): """Get available models with proper error handling""" try: response = requests.get( f"{BASE_URL}/v1/models/available", headers=headers, timeout=10 ) if response.status_code == 200: data = response.json() if data.get("success"): return data.get("models", []) else: print("❌ API returned success=false") return [] elif response.status_code == 401: print("❌ Authentication failed. Check your API key.") return [] elif response.status_code == 429: print("❌ Rate limit exceeded. Please wait before retrying.") return [] else: print(f"❌ HTTP {response.status_code}: {response.text}") return [] except requests.exceptions.Timeout: print("❌ Request timed out") return [] except requests.exceptions.ConnectionError: print("❌ Connection error") return [] except Exception as e: print(f"❌ Unexpected error: {e}") return [] # Use with fallback models = get_available_models_with_fallback() if models: print(f"Available models: {len(models)}") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} async function getAvailableModelsWithFallback() { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const response = await fetch(`${BASE_URL}/v1/models/available`, { method: 'GET', headers: headers, signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { if (response.status === 401) { console.log("❌ Authentication failed. Check your API key."); } else if (response.status === 429) { console.log("❌ Rate limit exceeded. Please wait before retrying."); } else { console.log(`❌ HTTP ${response.status}: ${await response.text()}`); } return []; } const data = await response.json(); if (!data.success) { console.log("❌ API returned success=false"); return []; } return data.models || []; } catch (error) { if (error.name === 'AbortError') { console.log("❌ Request timed out"); } else if (error.name === 'TypeError') { console.log("❌ Connection error"); } else { console.log(`❌ Unexpected error: ${error.message}`); } return []; } } // Use with fallback getAvailableModelsWithFallback().then(models => { if (models.length > 0) { console.log(`Available models: ${models.length}`); } }); ``` </Tab> </Tabs> ## Best Practices 1. **Cache Results**: Cache the models list to avoid frequent API calls 2. **Handle Changes**: Models may be added or removed over time 3. **Fallback Logic**: Always have fallback models for reliability 4. **Version Awareness**: Be aware of model versioning and deprecation 5. **Cost Monitoring**: Track usage costs for different models 6. **Performance Testing**: Test model performance for your specific use cases 7. **Documentation Review**: Check model-specific limitations and capabilities ## Integration Examples ### Model Selection in Agent Creation ```python theme={null} def create_agent_with_best_model(task_type): """Create an agent with the best available model for the task""" models = get_available_models() best_model = select_best_model(task_type) return { "agent_config": { "agent_name": f"{task_type.title()} Agent", "model_name": best_model, "max_tokens": 2048, "temperature": 0.7 }, "task": f"Perform {task_type} task" } ``` ### Batch Processing with Model Optimization ```python theme={null} def optimize_batch_processing(tasks): """Optimize model selection for batch processing""" optimized_payloads = [] for task in tasks: task_type = classify_task(task) best_model = select_best_model(task_type, "cost") optimized_payloads.append({ "agent_config": { "agent_name": f"Optimized Agent {len(optimized_payloads) + 1}", "model_name": best_model, "max_tokens": 1024 }, "task": task }) return optimized_payloads ``` # Multi-Agent Router Example Source: https://docs.swarms.ai/docs/examples/examples/multi-agent-router Build an IT helpdesk with intelligent ticket routing using MultiAgentRouter ## AI-Powered IT Helpdesk This example demonstrates how to build an intelligent ticket routing system that automatically dispatches requests to the right specialist using MultiAgentRouter. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define Specialist Agents Create specialized agents - the router will match tickets to the best-suited agent: ```python theme={null} def route_support_ticket(ticket_subject: str, ticket_description: str) -> dict: """Route a support ticket to the appropriate specialist.""" swarm_config = { "name": "IT Support Router", "description": "Intelligent IT support ticket routing", "swarm_type": "MultiAgentRouter", "task": f"""Process this IT support ticket: Subject: {ticket_subject} Description: {ticket_description} Provide diagnosis, step-by-step resolution, and estimated time to fix.""", "agents": [ { "agent_name": "Network Specialist", "description": "Handles VPN, WiFi, connectivity, and network issues", "system_prompt": "You are a Network Support Specialist. Handle connectivity, VPN, WiFi, DNS, and firewall issues. Provide diagnostic commands and step-by-step troubleshooting.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Security Analyst", "description": "Addresses security incidents, phishing, and access issues", "system_prompt": "You are an IT Security Analyst. Handle phishing reports, security incidents, and suspicious activity. For active threats, provide immediate containment steps.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Software Support", "description": "Resolves application issues and software installations", "system_prompt": "You are a Software Support Specialist. Handle application crashes, installation issues, and configuration problems. Provide clear numbered steps for resolution.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Hardware Technician", "description": "Manages device problems and equipment requests", "system_prompt": "You are a Hardware Support Technician. Handle computer, laptop, printer, and peripheral issues. Assess if on-site visit is needed and check warranty status.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Account Administrator", "description": "Handles password resets, permissions, and account access", "system_prompt": "You are an Account Administrator. Handle password resets, permission requests, and account lockouts. Never send passwords in tickets - use secure reset links.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=60 ) return response.json() ``` ### Step 3: Route Support Tickets ```python theme={null} # Sample tickets tickets = [ ("Cannot connect to VPN", "Getting 'Connection timed out' error when connecting to company VPN from home. Windows 11, Cisco AnyConnect."), ("Suspicious email received", "Got an email claiming to be from IT asking to verify my password. Sender: it-support@company-secure.com"), ("Excel keeps crashing", "Excel crashes when opening a large file with 50 tabs. Other files work fine. Office 365, Windows 10."), ("Password reset needed", "Locked out of my account. Self-service reset says security questions are wrong."), ] # Route each ticket for subject, description in tickets: result = route_support_ticket(subject, description) output = result.get("output", [{}])[0] routed_to = output.get("role", "Unknown") response_preview = output.get("content", "")[:200] print(f"\nTicket: {subject}") print(f"Routed to: {routed_to}") print(f"Response: {response_preview}...") print(f"Cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` Ticket: Cannot connect to VPN Routed to: Network Specialist Response: I'll help you troubleshoot this VPN connection issue. Let's diagnose systematically: 1. First, verify your internet connection: - Open Command Prompt and run: `ping 8.8.8.8`... Cost: $0.0234 Ticket: Suspicious email received Routed to: Security Analyst Response: Thank you for reporting this - you did the right thing by not clicking any links. This appears to be a PHISHING attempt. Key red flags: - Domain "company-secure.com" is not our official domain... Cost: $0.0198 Ticket: Excel keeps crashing Routed to: Software Support Response: I'll help you resolve this Excel crashing issue. Since other files work fine, the problem is likely with this specific file... Cost: $0.0215 Ticket: Password reset needed Routed to: Account Administrator Response: I understand you're locked out and need access urgently. Let me help you regain access securely... Cost: $0.0187 ``` <Note> The `description` field for each agent is critical - it helps the router decide which agent to send each task to. Be specific about each agent's domain. </Note> # News + Sentiment → Trade Idea Engine: Portfolio-Aware Source: https://docs.swarms.ai/docs/examples/examples/news-driven-trade-idea-engine A HierarchicalSwarm that turns a continuous news firehose into actionable, portfolio-overlapped trade theses in Slack within 60 seconds of publish. Two thousand articles cross the wire today. Eighty actually overlap your book. The engine posts a thesis on each of those eighty in Slack — and ignores the rest. ## What This Example Shows * A `HierarchicalSwarm` with a News Director coordinating four per-sector workers — Tech, Energy, Healthcare, Financials — running in parallel on each article * A continuous webhook ingestion path that accepts Bloomberg, Reuters, and AP feeds straight into a FastAPI endpoint * Function tools that hit your portfolio database for entity-to-ticker resolution, position-size lookup, and the only-fire-when-relevant overlap gate * A cheap Python pre-filter that runs *before* the swarm so 96% of the firehose never costs a token * A Trade Idea Synthesizer that emits a structured thesis straight to Slack — ticker, position size, sentiment, suggested action, time horizon, confidence * Sustained high-volume throughput with the observability needed to track a missed-news SLA <Info> This pipeline runs continuously against a 24/7 news firehose at sustained volume. Upgrade to Premium at [https://swarms.world/platform/account](https://swarms.world/platform/account) for the throughput headroom, priority processing, and the observability dashboard needed to monitor the missed-news SLA. See the [Production Observability Guide](/docs/guides/guides/production-observability) for the metrics that matter when news latency is the product. </Info> ## Why This Matters Most PMs are drowning in a news firehose where 99% of articles are irrelevant to their book — a tariff print on a name you don't hold is just noise, and by the time the analyst pod has read enough of the daily clip file to find the one piece that matters, the move has already happened. The alpha is in the 1% of articles that overlap a position you actually hold and carry a real signal, and that 1% needs to be in front of the PM in Slack within 60 seconds of the article publishing — not in the 8:30 AM morning meeting, not in the afternoon clip review, but now, before the desk you're competing against has finished reading the headline. This engine is the portfolio-aware filter that turns the firehose into exactly that: a Slack channel that only pings when something on your book just moved. ## The Architecture ``` ┌─────────────────────────────┐ │ Bloomberg / Reuters / AP │ │ News Webhook Feed │ └──────────────┬──────────────┘ │ ▼ ┌──────────────────────────┐ │ FastAPI /webhook/news │ └──────────────┬───────────┘ │ ▼ ┌──────────────────────────┐ │ Portfolio Overlap Gate │ │ (cheap Python pre-call) │ └──────────┬───────────────┘ │ overlap empty ─┴─ overlap non-empty │ │ ▼ ▼ ┌────────┐ ┌────────────────────────────────────────────┐ │ no-op │ │ HierarchicalSwarm │ │ (drop) │ │ ┌─────────────────────────────────────┐ │ └────────┘ │ │ News Director │ │ │ │ (claude-sonnet-4.5, coordinator) │ │ │ └────┬────────┬────────┬─────────┬────┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ │ │ │ Tech │ │Energy│ │ HC │ │Financials│ │ │ └──┬───┘ └──┬───┘ └──┬───┘ └────┬─────┘ │ │ └────┬───┴────┬───┴──────────┘ │ │ ▼ ▼ │ │ ┌─────────────────────────────────────┐ │ │ │ Trade Idea Synthesizer │ │ │ │ (claude-sonnet-4.5, output) │ │ │ └──────────────────┬──────────────────┘ │ └──────────────────────┼──────────────────────┘ │ ▼ ┌──────────────────┐ │ Slack #theses │ └──────────────────┘ ``` ## Step 1: Setup Install dependencies and pull your API key from [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ```bash theme={null} pip install requests fastapi uvicorn python-dotenv ``` ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" export NEWS_WEBHOOK_SECRET="shared-secret-with-bloomberg-or-reuters" export PORTFOLIO_DB_URL="postgresql://user:pass@db.internal:5432/book" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T.../B.../..." ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" PORTFOLIO_DB_URL = os.getenv("PORTFOLIO_DB_URL") SLACK_WEBHOOK_URL = os.getenv("SLACK_WEBHOOK_URL") NEWS_WEBHOOK_SECRET = os.getenv("NEWS_WEBHOOK_SECRET") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools The workers and the synthesizer share a toolbox that resolves entities to tickers, checks your actual book, scores sentiment, and posts the final thesis. Every tool follows the OpenAI function-call schema. ```python theme={null} EXTRACT_ENTITIES_TOOL = { "type": "function", "function": { "name": "extract_entities", "description": ( "Extract all company names, products, executives, and regulatory bodies " "mentioned in a news article. Return them as a normalized list." ), "parameters": { "type": "object", "properties": { "article_text": { "type": "string", "description": "The full body of the news article.", }, }, "required": ["article_text"], }, }, } LOOKUP_TICKERS_TOOL = { "type": "function", "function": { "name": "lookup_tickers_for_entity", "description": ( "Resolve a single named entity (company, subsidiary, product) into " "the list of public tickers it maps to in the firm's reference data." ), "parameters": { "type": "object", "properties": { "entity_name": { "type": "string", "description": "The normalized entity name.", }, }, "required": ["entity_name"], }, }, } IS_IN_BOOK_TOOL = { "type": "function", "function": { "name": "is_in_book", "description": ( "Return True if the firm currently holds a position in the given ticker " "according to the live portfolio database." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string", "description": "Ticker symbol."}, "portfolio_db": { "type": "string", "description": "Connection string for the portfolio database.", }, }, "required": ["ticker", "portfolio_db"], }, }, } COMPUTE_OVERLAP_TOOL = { "type": "function", "function": { "name": "compute_overlap", "description": ( "Given the tickers mentioned in an article and the firm's current book, " "return only the tickers that appear in both." ), "parameters": { "type": "object", "properties": { "article_tickers": { "type": "array", "items": {"type": "string"}, "description": "Tickers extracted from the article.", }, "book": { "type": "array", "items": {"type": "string"}, "description": "Tickers currently held by the firm.", }, }, "required": ["article_tickers", "book"], }, }, } SCORE_SENTIMENT_TOOL = { "type": "function", "function": { "name": "score_sentiment", "description": ( "Score the sentiment of the article specifically toward the named ticker. " "Return a float in [-1.0, 1.0] and a one-line rationale." ), "parameters": { "type": "object", "properties": { "article_text": {"type": "string"}, "ticker": {"type": "string"}, }, "required": ["article_text", "ticker"], }, }, } LOOKUP_POSITION_SIZE_TOOL = { "type": "function", "function": { "name": "lookup_position_size", "description": ( "Return the firm's current notional position size in USD for the given " "ticker. Used to size the suggested action." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string"}, "portfolio_db": {"type": "string"}, }, "required": ["ticker", "portfolio_db"], }, }, } POST_TRADE_THESIS_TOOL = { "type": "function", "function": { "name": "post_trade_thesis_to_slack", "description": ( "Post a fully-formed trade thesis to the #theses Slack channel. Should " "be called exactly once per overlapping ticker per article." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "The one-line thesis body to display in Slack.", }, "ticker": {"type": "string"}, "conviction": { "type": "string", "enum": ["LOW", "MEDIUM", "HIGH"], }, "action": { "type": "string", "enum": ["HOLD", "ADD", "REDUCE", "EXIT"], }, }, "required": ["text", "ticker", "conviction", "action"], }, }, } ALL_TOOLS = [ EXTRACT_ENTITIES_TOOL, LOOKUP_TICKERS_TOOL, IS_IN_BOOK_TOOL, COMPUTE_OVERLAP_TOOL, SCORE_SENTIMENT_TOOL, LOOKUP_POSITION_SIZE_TOOL, POST_TRADE_THESIS_TOOL, ] ``` ## Step 3: Define the Hierarchical Swarm The News Director runs on `claude-sonnet-4.5` because synthesizing multi-sector takes into a single coherent dispatch needs strong reasoning. The four sector workers run on `gpt-4.1-mini` — they are doing tight, scoped, per-sector reasoning over a single article, which is exactly the workload that cheap fast models eat for breakfast. The Trade Idea Synthesizer goes back to `claude-sonnet-4.5` because the final thesis is the artifact that lands in front of the PM. ```python theme={null} NEWS_DIRECTOR_PROMPT = ( "You are the News Director on a multi-sector trading desk. An article has just " "crossed the wire and at least one ticker on the firm's book is mentioned. " "Route the article to the relevant sector workers (Tech, Energy, Healthcare, " "Financials), collect their per-ticker takes, and hand a clean, deduplicated " "package of {ticker, sentiment, signal_strength, sector_take} to the Trade Idea " "Synthesizer. Do not write the thesis yourself — coordinate." ) SECTOR_WORKER_PROMPT_TEMPLATE = ( "You are the {sector} sector specialist. You have one job: for every ticker in " "your sector that the News Director hands you, use `extract_entities`, " "`score_sentiment`, and `lookup_position_size` as needed to write a tight " "per-ticker take covering (1) what the article actually says, (2) sentiment " "toward this specific ticker, (3) signal strength on a 1-5 scale, and (4) the " "single most important second-order implication for the position. No fluff." ) SYNTHESIZER_PROMPT = ( "You are the Trade Idea Synthesizer. Given the per-ticker takes from the sector " "workers, produce one structured trade thesis per overlapping ticker and call " "`post_trade_thesis_to_slack` exactly once for each. Each thesis is one line, " "ends with a clear HOLD / ADD / REDUCE / EXIT action, and includes the firm's " "current position size. Be decisive — the PM has 20 of these to read today." ) def build_news_swarm(article_text: str, article_url: str, overlap: list[str]) -> dict: return { "name": "News-Driven Trade Idea Engine", "description": ( "News Director coordinates sector workers and a Trade Idea Synthesizer " "to emit portfolio-overlapped trade theses to Slack." ), "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( f"Article URL: {article_url}\n" f"Overlapping book tickers: {', '.join(overlap)}\n\n" f"Article body:\n{article_text}\n\n" "Produce one trade thesis per overlapping ticker and post each to Slack." ), "agents": [ { "agent_name": "News Director", "description": "Coordinator — routes the article across sector workers.", "system_prompt": NEWS_DIRECTOR_PROMPT, "model_name": "claude-sonnet-4.5", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, }, { "agent_name": "Tech Sector Worker", "description": "Per-ticker takes for Tech sector names.", "system_prompt": SECTOR_WORKER_PROMPT_TEMPLATE.format(sector="Technology"), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": [ EXTRACT_ENTITIES_TOOL, SCORE_SENTIMENT_TOOL, LOOKUP_POSITION_SIZE_TOOL, ], }, { "agent_name": "Energy Sector Worker", "description": "Per-ticker takes for Energy sector names.", "system_prompt": SECTOR_WORKER_PROMPT_TEMPLATE.format(sector="Energy"), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": [ EXTRACT_ENTITIES_TOOL, SCORE_SENTIMENT_TOOL, LOOKUP_POSITION_SIZE_TOOL, ], }, { "agent_name": "Healthcare Sector Worker", "description": "Per-ticker takes for Healthcare sector names.", "system_prompt": SECTOR_WORKER_PROMPT_TEMPLATE.format(sector="Healthcare"), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": [ EXTRACT_ENTITIES_TOOL, SCORE_SENTIMENT_TOOL, LOOKUP_POSITION_SIZE_TOOL, ], }, { "agent_name": "Financials Sector Worker", "description": "Per-ticker takes for Financials sector names.", "system_prompt": SECTOR_WORKER_PROMPT_TEMPLATE.format(sector="Financials"), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, "tools_list_dictionary": [ EXTRACT_ENTITIES_TOOL, SCORE_SENTIMENT_TOOL, LOOKUP_POSITION_SIZE_TOOL, ], }, { "agent_name": "Trade Idea Synthesizer", "description": "Emits the final structured thesis to Slack.", "system_prompt": SYNTHESIZER_PROMPT, "model_name": "claude-sonnet-4.5", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, "tools_list_dictionary": [ LOOKUP_POSITION_SIZE_TOOL, POST_TRADE_THESIS_TOOL, ], }, ], } ``` ## Step 4: The FastAPI Webhook Endpoint The vendor (Bloomberg, Reuters, AP) POSTs every article to `/webhook/news`. The webhook does the cheap work first: extract entities, resolve to tickers, intersect with the live book. **Only if the overlap is non-empty does the swarm fire.** This is the single most important cost lever in the entire pipeline. ```python theme={null} import hmac import hashlib from fastapi import FastAPI, Header, HTTPException, Request app = FastAPI() def verify_webhook_signature(body: bytes, signature: str) -> bool: expected = hmac.new( NEWS_WEBHOOK_SECRET.encode(), body, hashlib.sha256, ).hexdigest() return hmac.compare_digest(expected, signature) # --- Local pre-call helpers (cheap, no LLM) ----------------------------------- def extract_entities_local(article_text: str) -> list[str]: """NER over the article body — spaCy / a small in-house model. No LLM.""" ... # your existing extractor def resolve_entities_to_tickers(entities: list[str]) -> list[str]: """Hit the firm's reference data table to map entities → tickers.""" ... # SQL against PORTFOLIO_DB_URL def get_current_book() -> set[str]: """Return the set of tickers currently held by the firm.""" ... # SQL against PORTFOLIO_DB_URL def portfolio_overlap(article_text: str) -> list[str]: entities = extract_entities_local(article_text) article_tickers = resolve_entities_to_tickers(entities) book = get_current_book() return sorted(set(article_tickers) & book) # --- The webhook ------------------------------------------------------------- @app.post("/webhook/news") async def news_webhook(request: Request, x_signature: str = Header(...)) -> dict: body = await request.body() if not verify_webhook_signature(body, x_signature): raise HTTPException(status_code=401, detail="bad signature") article = json.loads(body) article_text = article["body"] article_url = article["url"] # The gate. This is what keeps 96% of the firehose from ever touching an LLM. overlap = portfolio_overlap(article_text) if not overlap: return {"status": "dropped", "reason": "no portfolio overlap"} # Overlap is non-empty — fire the swarm. thesis_count = fire_swarm(article_text, article_url, overlap) return { "status": "processed", "overlap": overlap, "theses_posted": thesis_count, } ``` <Note> The overlap gate is the cost-control layer. At a full feed of \~2,000 articles/day, roughly 4% will mention something on the book — call it 80 articles. Every article that fails the gate costs you a few milliseconds of Python and zero tokens. Skip the gate and you're paying for 2,000 swarm runs to discover 1,920 of them weren't relevant. </Note> ## Step 5: The Per-Article Swarm Call When the gate passes, POST the article into the swarm. The `swarm_type` is `HierarchicalSwarm` — the News Director fans out to the four sector workers, collects their takes, and the Trade Idea Synthesizer calls `post_trade_thesis_to_slack` once per overlapping ticker. ```python theme={null} def fire_swarm(article_text: str, article_url: str, overlap: list[str]) -> int: payload = build_news_swarm(article_text, article_url, overlap) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=120, ) response.raise_for_status() result = response.json() # Count theses actually posted (Synthesizer calls post_trade_thesis_to_slack). synthesizer_output = next( (o for o in result.get("output", []) if "Trade Idea Synthesizer" in o.get("role", "")), {}, ) theses = synthesizer_output.get("tool_calls", []) or [] return len([t for t in theses if t.get("name") == "post_trade_thesis_to_slack"]) ``` ## Step 6: The Trade Thesis Output Schema Every thesis the synthesizer posts to Slack is a structured object. This is what your PM sees and what gets persisted into the research database for audit. ```json theme={null} { "ticker": "XOM", "position_size_usd": 12400000, "article_url": "https://www.reuters.com/business/energy/...", "sentiment": -0.62, "suggested_action": "REDUCE", "thesis_one_liner": "Saudi production guidance + softer Asian demand prints argue for a 25% trim into strength while crack spreads still support the multiple.", "time_horizon": "2-6 weeks", "confidence": "MEDIUM" } ``` | Field | Type | Notes | | ------------------- | ------ | -------------------------------------------------- | | `ticker` | string | Must be a ticker currently in the book | | `position_size_usd` | int | Pulled live via `lookup_position_size` | | `article_url` | string | Source link, always preserved for audit | | `sentiment` | float | `[-1.0, 1.0]` toward this specific ticker | | `suggested_action` | enum | `HOLD` / `ADD` / `REDUCE` / `EXIT` | | `thesis_one_liner` | string | One sentence. The PM reads 20 of these a day. | | `time_horizon` | string | e.g. `"intraday"`, `"2-6 weeks"`, `"1-2 quarters"` | | `confidence` | enum | `LOW` / `MEDIUM` / `HIGH` | ## Step 7: Production Observability At sustained continuous volume, observability is not optional — it is the SLA. The Premium observability dashboard tracks the metrics that matter when news latency *is* the product: articles ingested per minute, articles passing the overlap gate, swarm calls fired, theses posted to Slack, p50/p99 article-to-Slack latency, and — most importantly — the **missed-news SLA**: any article that overlapped the book but failed to produce a thesis within the 60-second budget. The dashboard, the priority processing queue that keeps the missed-news SLA inside the budget at peak earnings-week volume, and the per-route throughput headroom are Premium-tier features. See the [Production Observability Guide](/docs/guides/guides/production-observability) for the full set of metrics and alerting recipes. ## Real Cost vs. Bloomberg + Headcount The engine doesn't replace humans — it captures the 90% of relevance their day misses. At a full feed of \~2,000 articles/day, the overlap gate filters to \~80 swarm calls/day. | Line item | Volume | Cost | | ----------------------------------------- | ------------- | --------------------------- | | Articles ingested (gate only, no LLM) | \~2,000/day | \~\$0/day | | Swarm runs (post-gate, full hierarchical) | \~80/day | \~\$80/day | | **Engine total** | | **~~\$80/day (~~\$20K/yr)** | | Bloomberg terminal × 5 PMs | \$24K/seat/yr | \$120K/yr | | Sector-rotation analyst (fully loaded) | 1 FTE | \$200K/yr | | **Human stack total** | | **\$320K/yr** | The math isn't "fire the analyst." The math is: your sector-rotation analyst reads maybe 200 articles end-to-end on a heavy day and writes up the three they think matter. The engine reads all 2,000, identifies all 80 that overlap the book, and posts a structured thesis on each — for \$80/day. The analyst gets to spend their day on the five names that need real human judgement, and the desk stops missing the other 75. ## Next Steps * See the [AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) for the morning-meeting batch variant of the same hierarchical pattern * Read the [Production Observability Guide](/docs/guides/guides/production-observability) for the missed-news SLA dashboard and Premium-tier throughput configuration # OpenAI-Compatible Chat Completions Source: https://docs.swarms.ai/docs/examples/examples/openai-compatible Drop-in usage of the Swarms API with the OpenAI SDK — basic completion, streaming, multi-turn chat, and vision in Python, TypeScript, Go, and Rust. ## What This Example Shows * Using the Swarms API as a drop-in OpenAI replacement with zero code changes beyond `base_url` and `api_key` * Non-streaming and streaming completions * Multi-turn conversations with conversation history * Sending images (multimodal / vision) * Multi-loop agent reasoning via `max_loops` * Discovering available models with `client.models.list()` (`GET /v1/models`) * Error handling with SDK-native exception classes * Working examples in Python, TypeScript, Go, and Rust <Info> This endpoint uses the standard OpenAI request/response schema. Any existing OpenAI SDK code works by changing two config values. See the [API Reference](/docs/documentation/capabilities/openai-compatible) for the full schema. </Info> ## Prerequisites * A Swarms API key from [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) * The OpenAI SDK for your language installed <Tabs> <Tab title="Python"> ```bash theme={null} pip install openai python-dotenv ``` </Tab> <Tab title="TypeScript"> ```bash theme={null} npm install openai dotenv ``` </Tab> <Tab title="Go"> ```bash theme={null} go get github.com/openai/openai-go/v3 ``` </Tab> <Tab title="Rust"> ```bash theme={null} cargo add async-openai tokio futures ``` </Tab> </Tabs> Set your API key as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` *** ## 1. Basic Chat Completion The simplest usage — send a message, get a response. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a senior financial analyst."}, { "role": "user", "content": "Summarize the key risks of investing in emerging market bonds.", }, ], max_tokens=512, temperature=0.3, ) print(response.choices[0].message.content) print(f"\nUsage: {response.usage.prompt_tokens} in / {response.usage.completion_tokens} out") ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a senior financial analyst." }, { role: "user", content: "Summarize the key risks of investing in emerging market bonds.", }, ], max_tokens: 512, temperature: 0.3, }); console.log(response.choices[0].message.content); console.log( `\nUsage: ${response.usage?.prompt_tokens} in / ${response.usage?.completion_tokens} out` ); ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "context" "fmt" "log" "os" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey(os.Getenv("SWARMS_API_KEY")), option.WithBaseURL("https://api.swarms.world/v1"), ) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("You are a senior financial analyst."), openai.UserMessage("Summarize the key risks of investing in emerging market bonds."), }, MaxTokens: openai.Int(512), Temperature: openai.Float(0.3), }, ) if err != nil { log.Fatal(err) } fmt.Println(response.Choices[0].Message.Content) fmt.Printf("\nUsage: %d in / %d out\n", response.Usage.PromptTokens, response.Usage.CompletionTokens, ) } ``` </Tab> <Tab title="Rust"> ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; use std::env; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = OpenAIConfig::new() .with_api_key(env::var("SWARMS_API_KEY")?) .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestSystemMessageArgs::default() .content("You are a senior financial analyst.") .build()? .into(), ChatCompletionRequestUserMessageArgs::default() .content("Summarize the key risks of investing in emerging market bonds.") .build()? .into(), ]) .max_tokens(512_u32) .temperature(0.3) .build()?; let response = client.chat().create(request).await?; let choice = &response.choices[0]; if let Some(content) = &choice.message.content { println!("{}", content); } if let Some(usage) = &response.usage { println!("\nUsage: {} in / {} out", usage.prompt_tokens, usage.completion_tokens, ); } Ok(()) } ``` </Tab> </Tabs> ### Expected Output ``` Emerging market bonds carry several key risks: 1. **Currency Risk** — Local currency bonds can lose value when the issuing country's currency depreciates against the investor's home currency... 2. **Political and Sovereign Risk** — ... 3. **Liquidity Risk** — ... Usage: 38 in / 247 out ``` *** ## 2. Streaming Responses Stream the response as it's generated for a better user experience on longer outputs. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) print("Agent: ", end="", flush=True) stream = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a creative fiction writer."}, {"role": "user", "content": "Write a 3-paragraph short story about a robot discovering music for the first time."}, ], max_tokens=1024, temperature=0.8, stream=True, ) for chunk in stream: content = chunk.choices[0].delta.content if content: print(content, end="", flush=True) print("\n\n--- Stream complete ---") ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); process.stdout.write("Agent: "); const stream = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a creative fiction writer." }, { role: "user", content: "Write a 3-paragraph short story about a robot discovering music for the first time.", }, ], max_tokens: 1024, temperature: 0.8, stream: true, }); for await (const chunk of stream) { const content = chunk.choices[0]?.delta?.content; if (content) process.stdout.write(content); } console.log("\n\n--- Stream complete ---"); ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "context" "fmt" "log" "os" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey(os.Getenv("SWARMS_API_KEY")), option.WithBaseURL("https://api.swarms.world/v1"), ) fmt.Print("Agent: ") stream := client.Chat.Completions.NewStreaming(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("You are a creative fiction writer."), openai.UserMessage("Write a 3-paragraph short story about a robot discovering music for the first time."), }, MaxTokens: openai.Int(1024), Temperature: openai.Float(0.8), }, ) for stream.Next() { chunk := stream.Current() if len(chunk.Choices) > 0 { fmt.Print(chunk.Choices[0].Delta.Content) } } if err := stream.Err(); err != nil { log.Fatal(err) } fmt.Println("\n\n--- Stream complete ---") } ``` </Tab> <Tab title="Rust"> ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; use futures::StreamExt; use std::env; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = OpenAIConfig::new() .with_api_key(env::var("SWARMS_API_KEY")?) .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestSystemMessageArgs::default() .content("You are a creative fiction writer.") .build()? .into(), ChatCompletionRequestUserMessageArgs::default() .content("Write a 3-paragraph short story about a robot discovering music for the first time.") .build()? .into(), ]) .max_tokens(1024_u32) .temperature(0.8) .build()?; print!("Agent: "); let mut stream = client.chat().create_stream(request).await?; while let Some(result) = stream.next().await { match result { Ok(response) => { for choice in &response.choices { if let Some(ref content) = choice.delta.content { print!("{}", content); } } } Err(e) => eprintln!("\nError: {}", e), } } println!("\n\n--- Stream complete ---"); Ok(()) } ``` </Tab> </Tabs> *** ## 3. Multi-Turn Conversation (Chatbot) Build a conversational chatbot by accumulating messages across turns. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) messages = [ { "role": "system", "content": ( "You are a helpful coding assistant. " "When the user asks a question, provide clear, concise answers with code examples." ), }, ] # Turn 1 messages.append({"role": "user", "content": "How do I read a JSON file in Python?"}) response = client.chat.completions.create(model="gpt-4.1", messages=messages) assistant_reply = response.choices[0].message.content messages.append({"role": "assistant", "content": assistant_reply}) print(f"Assistant: {assistant_reply}\n") # Turn 2 — follows up on the first answer messages.append({"role": "user", "content": "How do I handle the case where the file doesn't exist?"}) response = client.chat.completions.create(model="gpt-4.1", messages=messages) assistant_reply = response.choices[0].message.content messages.append({"role": "assistant", "content": assistant_reply}) print(f"Assistant: {assistant_reply}\n") # Turn 3 — references context from both prior turns messages.append({"role": "user", "content": "Now combine both into a single reusable function."}) response = client.chat.completions.create(model="gpt-4.1", messages=messages) assistant_reply = response.choices[0].message.content print(f"Assistant: {assistant_reply}") ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); type Msg = OpenAI.Chat.Completions.ChatCompletionMessageParam; const messages: Msg[] = [ { role: "system", content: "You are a helpful coding assistant. Provide clear, concise answers with code examples.", }, ]; async function chat(userMessage: string): Promise<string> { messages.push({ role: "user", content: userMessage }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages, }); const reply = response.choices[0].message.content ?? ""; messages.push({ role: "assistant", content: reply }); return reply; } console.log("Turn 1:", await chat("How do I read a JSON file in Python?")); console.log("\nTurn 2:", await chat("How do I handle the case where the file doesn't exist?")); console.log("\nTurn 3:", await chat("Now combine both into a single reusable function.")); ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "context" "fmt" "log" "os" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey(os.Getenv("SWARMS_API_KEY")), option.WithBaseURL("https://api.swarms.world/v1"), ) messages := []openai.ChatCompletionMessageParamUnion{ openai.SystemMessage("You are a helpful coding assistant. Provide clear, concise answers with code examples."), } questions := []string{ "How do I read a JSON file in Python?", "How do I handle the case where the file doesn't exist?", "Now combine both into a single reusable function.", } for i, q := range questions { messages = append(messages, openai.UserMessage(q)) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: messages, }, ) if err != nil { log.Fatal(err) } reply := response.Choices[0].Message.Content messages = append(messages, openai.AssistantMessage(reply)) fmt.Printf("Turn %d:\n%s\n\n", i+1, reply) } } ``` </Tab> <Tab title="Rust"> ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestMessage, ChatCompletionRequestAssistantMessageArgs, ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, }, Client, }; use std::env; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = OpenAIConfig::new() .with_api_key(env::var("SWARMS_API_KEY")?) .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let mut messages: Vec<ChatCompletionRequestMessage> = vec![ ChatCompletionRequestSystemMessageArgs::default() .content("You are a helpful coding assistant. Provide clear, concise answers with code examples.") .build()? .into(), ]; let questions = [ "How do I read a JSON file in Python?", "How do I handle the case where the file doesn't exist?", "Now combine both into a single reusable function.", ]; for (i, question) in questions.iter().enumerate() { messages.push( ChatCompletionRequestUserMessageArgs::default() .content(*question) .build()? .into(), ); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(messages.clone()) .build()?; let response = client.chat().create(request).await?; let reply = response.choices[0] .message .content .clone() .unwrap_or_default(); messages.push( ChatCompletionRequestAssistantMessageArgs::default() .content(reply.as_str()) .build()? .into(), ); println!("Turn {}:\n{}\n", i + 1, reply); } Ok(()) } ``` </Tab> </Tabs> *** ## 4. Vision (Image Input) Send an image alongside your prompt using the multimodal content format. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ { "role": "user", "content": [ {"type": "text", "text": "What is shown in this image? Describe it in detail."}, { "type": "image_url", "image_url": { "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg" }, }, ], } ], max_tokens=512, ) print(response.choices[0].message.content) ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "user", content: [ { type: "text", text: "What is shown in this image? Describe it in detail." }, { type: "image_url", image_url: { url: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", }, }, ], }, ], max_tokens: 512, }); console.log(response.choices[0].message.content); ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "context" "fmt" "log" "os" "github.com/openai/openai-go/v3" "github.com/openai/openai-go/v3/option" ) func main() { client := openai.NewClient( option.WithAPIKey(os.Getenv("SWARMS_API_KEY")), option.WithBaseURL("https://api.swarms.world/v1"), ) response, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ Model: "gpt-4.1", Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage([]openai.ChatCompletionContentPartUnionParam{ { OfText: &openai.ChatCompletionContentPartTextParam{ Text: "What is shown in this image? Describe it in detail.", }, }, { OfImageURL: &openai.ChatCompletionContentPartImageParam{ ImageURL: openai.ChatCompletionContentPartImageImageURLParam{ URL: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", }, }, }, }), }, MaxTokens: openai.Int(512), }, ) if err != nil { log.Fatal(err) } fmt.Println(response.Choices[0].Message.Content) } ``` </Tab> <Tab title="Rust"> ```rust theme={null} use async_openai::{ config::OpenAIConfig, types::{ ChatCompletionRequestMessageContentPartImage, ChatCompletionRequestMessageContentPartText, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, ImageUrl, }, Client, }; use std::env; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = OpenAIConfig::new() .with_api_key(env::var("SWARMS_API_KEY")?) .with_api_base("https://api.swarms.world/v1"); let client = Client::with_config(config); let request = CreateChatCompletionRequestArgs::default() .model("gpt-4.1") .messages(vec![ ChatCompletionRequestUserMessageArgs::default() .content(vec![ ChatCompletionRequestMessageContentPartText::from( "What is shown in this image? Describe it in detail.", ) .into(), ChatCompletionRequestMessageContentPartImage::from(ImageUrl { url: "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg".to_string(), detail: None, }) .into(), ]) .build()? .into(), ]) .max_tokens(512_u32) .build()?; let response = client.chat().create(request).await?; if let Some(choice) = response.choices.first() { if let Some(content) = &choice.message.content { println!("{}", content); } } Ok(()) } ``` </Tab> </Tabs> *** ## 5. Multi-Loop Reasoning Use `max_loops` to let the agent iterate on its own output — useful for complex analysis, self-correction, or multi-step reasoning. Pass it via `extra_body` in the OpenAI SDK. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) response = client.chat.completions.create( model="gpt-4.1", messages=[ { "role": "system", "content": ( "You are a rigorous code reviewer. " "First write a solution, then review it for bugs, " "then provide the final corrected version." ), }, { "role": "user", "content": "Write a Python function that finds the longest palindromic substring in a string.", }, ], max_tokens=2048, extra_body={"max_loops": 3}, ) print(response.choices[0].message.content) print(f"\nTokens: {response.usage.total_tokens}") ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); const response = await client.chat.completions.create({ model: "gpt-4.1", messages: [ { role: "system", content: "You are a rigorous code reviewer. First write a solution, then review it for bugs, then provide the final corrected version.", }, { role: "user", content: "Write a Python function that finds the longest palindromic substring in a string.", }, ], max_tokens: 2048, // @ts-expect-error — Swarms extension field max_loops: 3, }); console.log(response.choices[0].message.content); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X POST https://api.swarms.world/v1/chat/completions \ -H "Authorization: Bearer $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4.1", "messages": [ {"role": "system", "content": "You are a rigorous code reviewer. First write a solution, then review it for bugs, then provide the final corrected version."}, {"role": "user", "content": "Write a Python function that finds the longest palindromic substring in a string."} ], "max_tokens": 2048, "max_loops": 3 }' ``` </Tab> </Tabs> <Info> `max_loops` is a Swarms extension — not part of the OpenAI spec. Default is `1` (single pass). The agent runs the specified number of reasoning loops, refining its output each iteration. </Info> *** ## 6. Model Discovery The SDK's built-in model listing works too — `GET /v1/models` returns every model available to your account (filtered by subscription tier) in the standard OpenAI list format. <Tabs> <Tab title="Python"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) models = client.models.list() print(f"{len(models.data)} models available\n") for model in models.data[:10]: print(f"{model.id} (owned_by: {model.owned_by})") ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import OpenAI from "openai"; import "dotenv/config"; const client = new OpenAI({ apiKey: process.env.SWARMS_API_KEY, baseURL: "https://api.swarms.world/v1", }); const models = await client.models.list(); console.log(`${models.data.length} models available\n`); for (const model of models.data.slice(0, 10)) { console.log(`${model.id} (owned_by: ${model.owned_by})`); } ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X GET https://api.swarms.world/v1/models \ -H "Authorization: Bearer $SWARMS_API_KEY" # Example response: # { # "object": "list", # "data": [ # {"id": "gpt-4.1", "object": "model", "created": 0, "owned_by": "openai"}, # {"id": "claude-sonnet-4-20250514", "object": "model", "created": 0, "owned_by": "anthropic"} # ] # } ``` </Tab> </Tabs> <Info> Prefer a plain list of model names with a count? Use the native Swarms endpoint `GET /v1/models/available` instead — see [Available Models](/docs/examples/examples/models-available). Both endpoints return the same tier-filtered catalog. </Info> *** ## 7. Putting It All Together — Research Assistant A complete example that combines system prompts, multi-turn conversation, and streaming to build a simple research assistant. ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) SYSTEM_PROMPT = """You are a research assistant specializing in technology trends. When asked about a topic: 1. Provide a concise overview 2. List 3-5 key developments 3. Identify potential implications 4. Cite timeframes where relevant Be specific and data-oriented. Avoid vague generalities.""" messages = [{"role": "system", "content": SYSTEM_PROMPT}] def ask(question: str) -> str: """Send a question and stream the response.""" messages.append({"role": "user", "content": question}) stream = client.chat.completions.create( model="gpt-4.1", messages=messages, max_tokens=1024, temperature=0.3, stream=True, ) full_response = [] for chunk in stream: content = chunk.choices[0].delta.content if content: print(content, end="", flush=True) full_response.append(content) reply = "".join(full_response) messages.append({"role": "assistant", "content": reply}) print("\n") return reply # Research session print("=== Research Session: AI Chip Industry ===\n") ask("What is the current state of the AI chip market in 2025?") ask("Which startups are challenging NVIDIA's dominance, and what approaches are they taking?") ask("Based on what you've told me, which of these challengers has the strongest technical moat?") ``` *** ## Environment Setup Create a `.env` file in your project directory: ```bash theme={null} SWARMS_API_KEY=your_api_key_here ``` ## Next Steps * [API Reference](/docs/documentation/capabilities/openai-compatible) — full request/response schema and field documentation * [Agent Completions](/docs/documentation/capabilities/agent) — the native Swarms endpoint with tools, MCP, and multi-loop support * [Streaming](/docs/examples/examples/streaming) — streaming with the native Swarms agent endpoint * [Vision](/docs/examples/examples/vision-capabilities) — more image/multimodal examples # Options Flow Detector: Unusual Activity to Trade Ideas Intraday Source: https://docs.swarms.ai/docs/examples/examples/options-flow-unusual-activity A ConcurrentWorkflow that scans options chains every 5 minutes, fans out flow, Greeks, and vol-surface analysis in parallel, and ships a ranked watchlist to Slack before the next print. Every 5 minutes during market hours, an unusual-activity watchlist lands in Slack — and the engineer who built it goes back to actually trading. ## What This Example Shows * A `ConcurrentWorkflow` of three specialist agents — Flow Scanner, Greeks Analyzer, Vol Surface Watcher — fanning out in parallel on the same options snapshot * Per-agent `tools_list_dictionary` wired to live options market-data endpoints (Polygon / Tradier) and a Slack webhook * An intraday cron firing every 5 minutes (`*/5 9-16 * * 1-5`) that turns into \~80 swarm runs per session * The rate-limit math: a 5-minute cadence is 12 requests per hour, comfortably inside the Free tier's 350/hour cap — what Premium buys you here is the priority queue, not raw call volume * Model diversification across providers — `gpt-4.1-mini`, `gpt-4.1`, `claude-haiku-4-5`, `claude-sonnet-4-5` — each picked for what that node actually needs * A Trade Idea Generator merging the three parallel briefs into a ranked watchlist and posting to a Slack channel before the next 5-minute window <Info> A 5-minute cron during the 6.5-hour cash session generates \~78 swarm runs per day, each launching 4 agents. Rate limits count API requests, not agents, so that is 12 requests/hour against the Free tier's 350/hour and 1,200/day caps — the reason to be on Premium here is the priority queue and the headroom, not the raw call count. Full limit table at [Rate Limits](/docs/documentation/resources/ratelimits). </Info> ## Why This Matters Unusual options activity has historically led equity returns by 10 to 30 minutes — large sweeps, abnormal volume-vs-OI ratios, IV expansions, and skew shifts are exactly the footprints big books leave when they take a directional view before it shows up in the tape. A single human eyeballing a Bloomberg flow scanner can cover maybe 20 names attentively in a session. The S\&P 500 has 500 names, the Russell 3000 has 3,000, the optionable US equity universe is roughly 5,000. You cannot scan that manually, and you cannot scan it once a day either — flow that mattered at 10:05 is dead by 10:35. The only way to win this is a 5-minute heartbeat with parallel specialist agents that survive the firehose and only escalate the names that actually deserve a look. ## The Architecture ``` ┌──────────────────────────────┐ │ Cron */5 9-16 * * 1-5 (NY) │ └──────────────┬───────────────┘ │ ▼ ┌─────────────────────────────────┐ │ Pull options chains │ │ • Polygon /v3/snapshot/options │ │ • Tradier /markets/options │ └─────────────┬───────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ ConcurrentWorkflow │ │ ┌─────────────┐ ┌──────────┐ ┌────────┐ │ │ │ Flow Scanner│ │ Greeks │ │ Vol │ │ │ │ gpt-4.1-mini│ │ Analyzer │ │ Surface│ │ │ │ │ │ gpt-4.1 │ │ haiku │ │ │ └──────┬──────┘ └────┬─────┘ └───┬────┘ │ └────────┼─────────────┼───────────┼──────┘ │ │ │ └─────────────┼───────────┘ ▼ ┌─────────────────────────────────┐ │ Trade Idea Generator │ │ claude-sonnet-4-5 │ │ (merge → rank → conviction) │ └─────────────┬───────────────────┘ ▼ ┌─────────────────────────────────┐ │ Slack #options-flow │ └─────────────────────────────────┘ ``` ## Step 1: Setup Grab your Swarms key at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys), then wire up the options data vendor and Slack. ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-swarms-key" export POLYGON_API_KEY="your-polygon-key" # or TRADIER_TOKEN export TRADIER_TOKEN="your-tradier-token" export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T.../B.../..." ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Tools are OpenAI function-call schemas attached per-agent via `tools_list_dictionary`. The agents decide when to call them — your backend executes them against Polygon / Tradier / Slack and feeds results back into the loop. ```python theme={null} FETCH_OPTIONS_CHAIN = { "type": "function", "function": { "name": "fetch_options_chain", "description": ( "Pull the live options chain for an underlying ticker across a " "near-term expiry range. Returns strikes, bid/ask, IV, volume, and " "open interest per contract." ), "parameters": { "type": "object", "properties": { "symbol": { "type": "string", "description": "Underlying ticker, e.g. 'NVDA'.", }, "expiry_range": { "type": "string", "description": ( "ISO date range, e.g. '2026-05-30:2026-06-20'. " "Limit to weeklies + front month for flow work." ), }, }, "required": ["symbol", "expiry_range"], }, }, } COMPUTE_GREEKS = { "type": "function", "function": { "name": "compute_greeks", "description": ( "Compute Black-Scholes delta, gamma, vega, theta, rho for a " "single contract given strike, IV, expiry, underlying spot, " "and risk-free rate." ), "parameters": { "type": "object", "properties": { "strike": {"type": "number", "description": "Strike price."}, "iv": {"type": "number", "description": "Implied vol as a decimal, e.g. 0.42."}, "expiry": {"type": "string", "description": "ISO expiry date."}, "underlying": {"type": "number", "description": "Spot price of the underlying."}, "rfr": {"type": "number", "description": "Risk-free rate as a decimal, e.g. 0.045."}, }, "required": ["strike", "iv", "expiry", "underlying", "rfr"], }, }, } VOLUME_VS_OI_RATIO = { "type": "function", "function": { "name": "volume_vs_oi_ratio", "description": ( "Return today's contract-level volume / open interest ratio for " "every strike on the chain. Ratios > 2.0 are the headline " "unusual-activity tell." ), "parameters": { "type": "object", "properties": { "symbol": {"type": "string", "description": "Underlying ticker."}, }, "required": ["symbol"], }, }, } COMPUTE_IV_RANK = { "type": "function", "function": { "name": "compute_iv_rank", "description": ( "Compute IV rank (0-100) for the at-the-money 30-day vol vs. its " "trailing window. High IV rank = vol is rich, sellers favored. " "Low IV rank = vol is cheap, gamma is on sale." ), "parameters": { "type": "object", "properties": { "symbol": {"type": "string", "description": "Underlying ticker."}, "lookback_days": { "type": "integer", "description": "Lookback window in trading days, e.g. 252.", }, }, "required": ["symbol", "lookback_days"], }, }, } POST_SLACK_ALERT = { "type": "function", "function": { "name": "post_slack_alert", "description": ( "Post a formatted unusual-activity alert to the #options-flow " "Slack channel via the configured webhook." ), "parameters": { "type": "object", "properties": { "text": { "type": "string", "description": "Full markdown body of the alert.", }, "ticker": { "type": "string", "description": "Headline ticker for the alert.", }, "conviction": { "type": "string", "enum": ["LOW", "MEDIUM", "HIGH"], "description": "Conviction bucket, drives channel emoji + colour bar.", }, }, "required": ["text", "ticker", "conviction"], }, }, } ``` ## Step 3: Define the Four Agents Four agents, four models, four jobs. Cheap and fast on the wide scan; reasoning-heavy where the math actually matters; Sonnet at the top to merge. ```python theme={null} FLOW_SCANNER_PROMPT = ( "You are an Options Flow Scanner. For the given universe of tickers, call " "fetch_options_chain and volume_vs_oi_ratio to flag contracts with " "volume/OI > 2.0, abnormal block prints, and sweeps that hit the ask. " "Return a tight list of (ticker, strike, expiry, side, V/OI, $premium). " "No prose. No hedging. Be fast — you are the first pass." ) GREEKS_ANALYZER_PROMPT = ( "You are a Greeks Analyzer. For each contract surfaced by the Flow Scanner, " "call compute_greeks and report delta exposure, gamma per $1 move, vega per " "vol point, and the dollar size of the position. Flag any single trade with " "more than $250k notional gamma or vega. Output one line per contract." ) VOL_SURFACE_PROMPT = ( "You are a Vol Surface Watcher. For each underlying flagged by Flow Scanner, " "call compute_iv_rank with lookback_days=252 and read the chain for skew " "shifts and term-structure dislocations vs. the prior snapshot. Flag IV " "rank > 70 (rich vol) and < 20 (cheap vol). Note any 25-delta skew that " "moved more than 2 vol points in the last hour." ) TRADE_IDEA_PROMPT = ( "You are the Trade Idea Generator. Merge the Flow Scanner, Greeks Analyzer, " "and Vol Surface Watcher briefs into a ranked watchlist. For each idea:\n\n" "TICKER: <symbol>\n" "STRUCTURE: <single-leg or spread>\n" "THESIS: <one sentence on why this flow matters now>\n" "CONVICTION: <LOW | MEDIUM | HIGH>\n" "INVALIDATION: <one sentence on what would kill the idea>\n\n" "Then call post_slack_alert for every MEDIUM and HIGH conviction idea. " "Skip LOW conviction — Slack is not a log file." ) def build_options_flow_swarm(universe: list[str]) -> dict: return { "name": "Options Flow Detector", "description": "ConcurrentWorkflow scanning unusual options activity intraday.", "swarm_type": "ConcurrentWorkflow", "max_loops": 1, "task": ( "Scan the following universe for unusual options activity in the " "last 5 minutes and produce a ranked watchlist of trade ideas: " f"{', '.join(universe)}" ), "agents": [ { "agent_name": "Flow Scanner", "description": "First-pass unusual-activity scan across the universe.", "system_prompt": FLOW_SCANNER_PROMPT, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, "tools_list_dictionary": [FETCH_OPTIONS_CHAIN, VOLUME_VS_OI_RATIO], }, { "agent_name": "Greeks Analyzer", "description": "Delta / gamma / vega / theta sizing on flagged contracts.", "system_prompt": GREEKS_ANALYZER_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, "tools_list_dictionary": [COMPUTE_GREEKS], }, { "agent_name": "Vol Surface Watcher", "description": "IV rank, skew, and term-structure dislocations.", "system_prompt": VOL_SURFACE_PROMPT, "model_name": "claude-haiku-4-5", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, "tools_list_dictionary": [COMPUTE_IV_RANK, FETCH_OPTIONS_CHAIN], }, { "agent_name": "Trade Idea Generator", "description": "Merges briefs into a ranked watchlist and posts to Slack.", "system_prompt": TRADE_IDEA_PROMPT, "model_name": "claude-sonnet-4-5", "role": "coordinator", "max_loops": 1, "max_tokens": 6144, "temperature": 0.3, "tools_list_dictionary": [POST_SLACK_ALERT], }, ], } ``` <Note> The cheapest model (`gpt-4.1-mini`) does the widest pass because flow scanning is mostly pattern recognition over structured data — Greeks reasoning and final ranking is where the smarter models earn their tokens. Diversifying providers across OpenAI and Anthropic also means if one provider has a 5-minute outage, three out of four agents still ship. </Note> ## Step 4: Run One Intraday Pass ```python theme={null} UNIVERSE = [ "SPY", "QQQ", "IWM", "NVDA", "AAPL", "MSFT", "GOOGL", "META", "AMZN", "TSLA", "AMD", "AVGO", "NFLX", "COIN", "PLTR", "SMCI", "MSTR", "JPM", "BAC", "XOM", "OXY", ] def run_options_flow_pass(universe: list[str]) -> dict: payload = build_options_flow_swarm(universe) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() if __name__ == "__main__": result = run_options_flow_pass(UNIVERSE) for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600]) cost = result["usage"]["billing_info"]["total_cost"] elapsed = result["execution_time"] print(f"\nPass cost: ${cost:.4f} | wall time: {elapsed:.1f}s") ``` A single 21-ticker pass typically runs \~\$0.18–\$0.25 and completes in 30–45 seconds — well inside the 5-minute window, with a generous buffer for slow data calls. ## Step 5: The 5-Minute Cron Drop the script behind a cron line that only fires during the US cash session, Monday through Friday. ```cron theme={null} # /etc/cron.d/options-flow (server is on America/New_York) */5 9-16 * * 1-5 trader /usr/bin/python3 /opt/flow/run_pass.py >> /var/log/flow.log 2>&1 ``` The math on a 5-minute heartbeat: | Window | Passes | | -------------------- | ------- | | Per hour | 12 | | Per 6.5-hour session | \~78 | | Per week | \~390 | | Per month | \~1,700 | Each pass launches the swarm, which kicks off 4 agents and the underlying tool calls. That is roughly 312 agent-runs per hour during market hours, but rate limits count requests, not agents: 12 requests/hour sits well inside the Free tier's 350/hour and 1,200/day caps. Production still wants **Premium** for the priority processing queue and the headroom not to drop a window when the chain endpoint is slow. Full numbers at [Rate Limits](/docs/documentation/resources/ratelimits). <Info> Premium queue priority matters more than raw call count here. A 5-minute window that completes at minute 6 is a missed window — the next cron fires before the last alert lands in Slack. Priority routing keeps the wall time inside the cadence on busy days. </Info> ## Real Cost vs. Bloomberg Options Scanner | Stack | Setup | Annual | | ------------------------------------------- | ----------------------------- | ---------------------- | | This swarm (4 agents × \~78 passes/day) | \~\$15/day in API + data fees | \~\$3,750/yr | | Bloomberg AIM seat (with options analytics) | \$2,000/mo per seat | \~\$24,000/yr | | Tradeshift / OptionsPlay enterprise | \$1,500–\$3,000/mo | \~\$18,000–\$36,000/yr | This is not a Bloomberg replacement. Nobody is canceling their Terminal because of a Slack bot — Bloomberg owns the ground truth, the chat, and the workflow your counterparties live in. What this stack is: a focused alpha layer on top of the data you already pay for, doing the one thing humans cannot do — scanning the full optionable universe every 5 minutes without getting tired. Cheap enough to run from a side server, cheap enough to fail occasionally, cheap enough that you do not have to justify the spend to a CFO. ## Next Steps * [Crypto Quant Agent](/docs/examples/examples/crypto-quant-agent) — the same intraday cron pattern applied to 24/7 crypto markets where the heartbeat can stay tight all weekend * [AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) — the overnight `HierarchicalSwarm` batch pattern that pairs with this intraday loop for a complete research stack * [Rate Limits](/docs/documentation/resources/ratelimits) — exact per-tier numbers, the upgrade path, and how priority queueing changes the cadence math # Build Your Personal AI Chief of Staff with Gmail, Calendar, and Notion Source: https://docs.swarms.ai/docs/examples/examples/personal-ai-chief-of-staff Wire one conversational Swarms agent into Gmail, Google Calendar, and Notion via MCP — and get an AI Chief of Staff that runs your day for under $1. ## What This Example Shows * Plugging three live MCP servers (Gmail, Google Calendar, Notion) into a single agent via `mcp_configs` * Carrying conversation history across a full day so the agent remembers what you talked about at 9am when you ping it again at 4pm * Sub-agent delegation: a main Chief of Staff that hands off to specialists (Inbox Triager, Meeting Prep, Notion Logger) when it's time to do real work * Structured outputs for clean calendar slots and Notion rows * An idiomatic Python CLI loop you can paste into a terminal and start using today * A cron-style 7am inbox digest you can deploy as your morning routine <Info> Grab a free Swarms API key at [swarms.world](https://swarms.world). The Gmail, Google Calendar, and Notion MCP servers shown here are **pluggable** — point `mcp_url` at any hosted MCP endpoint that exposes those tools (Composio, Zapier MCP, Pipedream, your own). If you're new to MCP, start with [MCP Integration](/docs/examples/examples/mcp-integration). </Info> ## Why This Matters A great Chief of Staff does three things: triages your inbox so you only see what matters, runs your calendar so you never double-book or miss prep, and keeps your second brain (Notion) up to date so context never falls through the cracks. An AI Chief of Staff does the same job in roughly 50 lines of Python, runs you about \$0.20/day in API spend, and doesn't need a 1:1. The trick is wiring one conversational agent into the three tools a real CoS actually lives in — and letting it remember everything you said earlier in the day. ## The Architecture ``` You (CLI / Slack / iMessage) | v +---------------------------+ | Main Chief of Staff | | (claude-sonnet-4.5) | | + conversation_history | +---------------------------+ | | | | MCP tools attached: | - Gmail | - Google Calendar | - Notion | | delegates to sub-agents when work gets specialized v +-----------------+-----------------+-----------------+ | | | | v v v v +---------------+ +---------------+ +---------------+ | Inbox Triager | | Meeting Prep | | Notion Logger | | (haiku-4.5) | | (gpt-4.1-mini)| | (haiku-4.5) | +---------------+ +---------------+ +---------------+ ``` The main CoS is the only agent you ever talk to. It decides when a request needs a specialist and delegates. The sub-agents inherit access to the MCP tools they need and return structured results back to the main agent, which then talks back to you in plain English. ## Step 1: Setup You'll need four environment variables. The three MCP URLs are hosted endpoints **you control** — either via a provider like Composio/Pipedream/Zapier MCP or your own server. Each one exposes a different toolset to the agent. ```bash theme={null} export SWARMS_API_KEY="sk-..." export GMAIL_MCP_URL="https://mcp.composio.dev/gmail/<your-account-id>" export GCAL_MCP_URL="https://mcp.composio.dev/googlecalendar/<your-account-id>" export NOTION_MCP_URL="https://mcp.composio.dev/notion/<your-account-id>" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" GMAIL_MCP_URL = os.getenv("GMAIL_MCP_URL") GCAL_MCP_URL = os.getenv("GCAL_MCP_URL") NOTION_MCP_URL = os.getenv("NOTION_MCP_URL") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Three Sub-Agents Each sub-agent is tightly scoped to one job. Keep the system prompts short — these aren't generalists, they're specialists the main CoS calls when it needs work done. ```python theme={null} INBOX_TRIAGER = { "agent_name": "Inbox-Triager", "description": "Classifies and summarizes recent Gmail messages into priority buckets.", "system_prompt": ( "You triage Gmail. For each message you read, classify it as " "URGENT, FOLLOW-UP, FYI, or NOISE. Summarize the actually-important " "ones in one line each, with sender and subject. Skip newsletters, " "calendar invites, and notifications unless they require a response. " "Return a compact digest grouped by priority bucket." ), "model_name": "claude-haiku-4.5", "max_loops": "auto", "mcp_url": GMAIL_MCP_URL, } MEETING_PREP = { "agent_name": "Meeting-Prep", "description": "Pulls upcoming calendar events and drafts a prep brief.", "system_prompt": ( "You prepare the user for upcoming meetings. Read the next 24-72 hours " "of calendar events, identify the attendees, and produce a one-paragraph " "brief per meeting: who, what it's about, what to bring or decide, and " "any obvious recent email thread context. When asked, email the brief " "to the user." ), "model_name": "gpt-4.1-mini", "max_loops": "auto", "mcp_configs": { "connections": [ {"url": GCAL_MCP_URL}, {"url": GMAIL_MCP_URL}, ] }, } NOTION_LOGGER = { "agent_name": "Notion-Logger", "description": "Appends structured notes and updates to Notion pages and databases.", "system_prompt": ( "You write to Notion. When the user mentions a deal, person, or project, " "find the right page or database row and append a structured note with " "today's date. Do not create duplicates — search first. Keep notes " "concise and factual; one bullet per fact." ), "model_name": "claude-haiku-4.5", "max_loops": "auto", "mcp_url": NOTION_MCP_URL, } ``` <Note> Sub-agents inherit `max_loops="auto"` so they can call MCP tools repeatedly until the task is done — read a thread, then reply; search Notion, then append. The main CoS doesn't need to micromanage them. </Note> ## Step 3: Wire Up the Main Chief of Staff Agent The main agent gets all three MCP servers attached *and* a roster of the three sub-agents under `handoffs`. It uses `claude-sonnet-4.5` because the orchestration model matters most — it's the one deciding when to delegate vs. just answer. ```python theme={null} def build_cos_config(): return { "agent_name": "Chief-of-Staff", "description": ( "Personal Chief of Staff with live access to Gmail, Google Calendar, " "and Notion. Delegates specialized work to a team of sub-agents." ), "system_prompt": ( "You are the user's personal Chief of Staff. You have live access to " "their Gmail, Google Calendar, and Notion via MCP tools, and you can " "delegate to three specialist sub-agents: Inbox-Triager, Meeting-Prep, " "and Notion-Logger.\n\n" "Rules:\n" "- Default to action. If the user says 'schedule X', schedule it; " " don't ask which calendar unless there's genuine ambiguity.\n" "- Delegate when the work is bulk or specialized. A single 'reply to " " Sarah' you handle yourself. 'Triage my inbox' goes to Inbox-Triager.\n" "- Remember context from earlier in the conversation. If the user " " mentioned the Acme deal at 9am, that's the same Acme at 4pm.\n" "- For calendar slots, return them as structured ISO datetimes.\n" "- Talk like a competent human CoS, not a chatbot. No 'I'd be happy to'." ), "model_name": "claude-sonnet-4.5", "max_loops": "auto", "max_tokens": 8192, "temperature": 0.2, "mcp_configs": { "connections": [ {"url": GMAIL_MCP_URL}, {"url": GCAL_MCP_URL}, {"url": NOTION_MCP_URL}, ] }, "handoffs": [INBOX_TRIAGER, MEETING_PREP, NOTION_LOGGER], } def call_cos(task: str, history: list | None = None) -> dict: payload = {"agent_config": build_cos_config(), "task": task} if history: payload["history"] = history response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() def extract_reply(result: dict) -> str: outputs = result.get("outputs") if isinstance(outputs, list): for item in reversed(outputs): if not isinstance(item, dict): continue role = (item.get("role") or "").lower() if role in ("user", "system"): continue content = item.get("content") if isinstance(content, list): return " ".join(str(c) for c in content) if content: return str(content) return json.dumps(outputs or result, indent=2) ``` ## Step 4: The CLI Loop with Conversation History This is the part you'll actually use. A tiny REPL that accumulates messages across turns so the CoS remembers everything you said today. ```python theme={null} def cos_repl(): history: list[dict] = [] print("Chief of Staff online. Ctrl-C to quit.\n") while True: try: user_msg = input("you > ").strip() except (EOFError, KeyboardInterrupt): print() break if not user_msg: continue result = call_cos(task=user_msg, history=history or None) reply = extract_reply(result) print(f"cos > {reply}\n") history.append({"role": "user", "content": user_msg}) history.append({"role": "assistant", "content": reply}) if __name__ == "__main__": cos_repl() ``` Three real interactions, all in the same session, all relying on history: ``` you > what did Sarah email me about yesterday? cos > Sarah Chen sent two threads yesterday. The big one is the Q3 partnership proposal — she's asking for a call this week to walk through the revised terms (she dropped the rev-share ask from 30% to 22%). The other is a quick heads-up that she'll be OOO Friday. Want me to propose times for the call? you > yeah, schedule contract review with Sarah Thursday after 3 cos > Booked. Thursday 3:30-4:30pm with Sarah Chen, titled "Q3 Partnership — Contract Review." Invite sent to sarah@acmecorp.com with the revised terms PDF from yesterday's thread attached. Calendar link is in your inbox. you > add a note to the Acme deal in notion: they want net-60 terms cos > Logged. Appended to "Acme Corp — Q3 Partnership" in your Deals database under today's date: "Acme requested net-60 payment terms (vs. our standard net-30). Surfaced during contract review prep, 5/28." ``` Notice what's happening: * Turn 1: the CoS delegates inbox reading to **Inbox-Triager**, then summarizes. * Turn 2: the CoS calls **Google Calendar MCP** directly (single action, no delegation needed), pulls Sarah's email from history, attaches the PDF. * Turn 3: "Acme" is never disambiguated — the CoS knows it's Sarah Chen's company from the prior two turns and delegates to **Notion-Logger** to find the right database row. <Warning> The Swarms API is stateless. The CoS only "remembers" because you're threading `history` on every request. If you stop appending, it forgets — same as any other multi-turn agent. See [Conversation History](/docs/examples/examples/conversation-history) for the full pattern. </Warning> ## Step 5: Deploy It as a Daily 7AM Inbox Digest The CLI is great for the day-to-day. The real flex is letting your CoS proactively brief you before you've even opened your laptop. Drop this into a cron job at 7am and you'll get a digest email every morning. ```python theme={null} # digest.py — run via cron: 0 7 * * * /usr/bin/python3 /path/to/digest.py def morning_digest(): payload = { "agent_config": build_cos_config(), "task": ( "It's 7am. Run my morning routine:\n" "1. Delegate to Inbox-Triager: read the last 18 hours of email and " " give me the URGENT and FOLLOW-UP buckets only.\n" "2. Delegate to Meeting-Prep: brief me on every meeting today and " " tomorrow morning.\n" "3. Compose the combined digest as a single email, subject " " \"Morning Brief — <today's date>\", and send it to me via Gmail.\n" "Be terse. I'm reading this with one eye open." ), } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=600, ) response.raise_for_status() print(extract_reply(response.json())) if __name__ == "__main__": morning_digest() ``` Schedule it: ```bash theme={null} crontab -e # add: 0 7 * * * /usr/bin/python3 /Users/you/cos/digest.py >> /tmp/cos.log 2>&1 ``` That's it. Your inbox lands in your inbox, with the noise stripped out, before your coffee is done. ## What You Just Built About 50 lines of Python, three MCP URLs, and you now have: * An always-on Chief of Staff that lives in your terminal (or wherever you wire the loop next — Slack, iMessage, a web app) * Continuity across the entire day via conversation history * Specialist sub-agents that handle the heavy lifting (inbox triage, meeting prep, Notion logging) without you ever having to name them * A 7am morning brief delivered to your real inbox, automatically It's a 50-line replacement for a \$90K/yr executive assistant — minus the calendar tetris frustration, the back-and-forth scheduling threads, and the part where they need to sleep. Costs roughly \$0.20/day to run at moderate volume. ## Next Steps * [MCP Integration](/docs/examples/examples/mcp-integration) — full reference for `mcp_url`, `mcp_configs`, auth headers, and multi-server setups * [Sub-Agent Delegation](/docs/examples/examples/sub-agent-delegation) — how the main agent dynamically picks and runs specialists * [Conversation History](/docs/examples/examples/conversation-history) — the exact `history` shape and the mistakes to avoid when threading multi-turn context # Estimate Costs from Pricing Details Source: https://docs.swarms.ai/docs/examples/examples/pricing-cost-estimator Use comprehensive pricing details to estimate end-to-end workload costs Leverage the `/v1/usage/costs` endpoint to **estimate end-to-end workload costs** before running large jobs. This example shows how to turn the unified pricing model into a simple cost calculator. <Info> All cost values are returned in **USD**. Always re-fetch pricing in long‑lived services to reflect updates in real time. </Info> ## Example: Cost Estimation Workflow The following examples: * **Fetch** pricing details from `/v1/usage/costs` * **Estimate** costs for: * Swarm completions (input/output tokens + per‑agent fee) * Agent completions (input/output tokens) * Images, MCP calls, search, and scrape operations * Optional **night-time discount** multiplier (applies to swarm completion token costs only) <Tabs> <Tab title="Python"> ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def get_pricing(): resp = requests.get(f"{BASE_URL}/v1/usage/costs", headers=headers) resp.raise_for_status() return resp.json()["usage_pricing"] def estimate_cost(usage_pricing: dict, *, swarm_input_tokens: int = 0, swarm_output_tokens: int = 0, swarm_agents: int = 0, agent_input_tokens: int = 0, agent_output_tokens: int = 0, images: int = 0, mcp_calls: int = 0, searches: int = 0, scrapes: int = 0, night_time: bool = False) -> float: up = usage_pricing def tokens_to_m(tokens: int) -> float: return tokens / 1_000_000.0 cost = 0.0 # Swarm completions (the night-time discount applies only to # swarm input/output token costs, not the per-agent fee) swarm_token_cost = ( tokens_to_m(swarm_input_tokens) * up["swarm_completions_input_cost_per_1m"] + tokens_to_m(swarm_output_tokens) * up["swarm_completions_output_cost_per_1m"] ) if night_time: swarm_token_cost *= up["night_time_discount"] cost += swarm_token_cost cost += swarm_agents * up["swarm_completions_agent_cost"] # Agent completions cost += tokens_to_m(agent_input_tokens) * up["agent_completions_input_cost_per_1m"] cost += tokens_to_m(agent_output_tokens) * up["agent_completions_output_cost_per_1m"] # Images, MCP, search, scrape cost += images * up["agent_completions_img_cost"] cost += mcp_calls * up["agent_completions_mcp_cost"] cost += searches * up["search_cost"] cost += scrapes * up["scrape_cost"] return round(cost, 6) if __name__ == "__main__": pricing = get_pricing() est = estimate_cost( pricing, swarm_input_tokens=800_000, swarm_output_tokens=400_000, swarm_agents=3, agent_input_tokens=500_000, agent_output_tokens=250_000, images=4, mcp_calls=10, searches=20, scrapes=5, night_time=True, ) print(f"💰 Estimated workload cost: ${est}") ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' type UsagePricingModel = { swarm_completions_agent_cost: number swarm_completions_input_cost_per_1m: number swarm_completions_output_cost_per_1m: number agent_completions_input_cost_per_1m: number agent_completions_output_cost_per_1m: number agent_completions_img_cost: number agent_completions_mcp_cost: number search_cost: number scrape_cost: number night_time_discount: number } async function getPricing(): Promise<UsagePricingModel> { if (!API_KEY) throw new Error('SWARMS_API_KEY is not set') const res = await fetch(`${BASE_URL}/v1/usage/costs`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, }) if (!res.ok) { const body = await res.text() throw new Error(`HTTP ${res.status}: ${body}`) } const json = (await res.json()) as { usage_pricing: UsagePricingModel } return json.usage_pricing } function tokensToM(tokens: number): number { return tokens / 1_000_000 } function estimateCost( up: UsagePricingModel, opts: { swarmInputTokens?: number swarmOutputTokens?: number swarmAgents?: number agentInputTokens?: number agentOutputTokens?: number images?: number mcpCalls?: number searches?: number scrapes?: number nightTime?: boolean }, ): number { const { swarmInputTokens = 0, swarmOutputTokens = 0, swarmAgents = 0, agentInputTokens = 0, agentOutputTokens = 0, images = 0, mcpCalls = 0, searches = 0, scrapes = 0, nightTime = false, } = opts let cost = 0 // Swarm completions (the night-time discount applies only to // swarm input/output token costs, not the per-agent fee) let swarmTokenCost = tokensToM(swarmInputTokens) * up.swarm_completions_input_cost_per_1m + tokensToM(swarmOutputTokens) * up.swarm_completions_output_cost_per_1m if (nightTime) swarmTokenCost *= up.night_time_discount cost += swarmTokenCost cost += swarmAgents * up.swarm_completions_agent_cost cost += tokensToM(agentInputTokens) * up.agent_completions_input_cost_per_1m cost += tokensToM(agentOutputTokens) * up.agent_completions_output_cost_per_1m cost += images * up.agent_completions_img_cost cost += mcpCalls * up.agent_completions_mcp_cost cost += searches * up.search_cost cost += scrapes * up.scrape_cost return Number(cost.toFixed(6)) } async function main() { const pricing = await getPricing() const estimate = estimateCost(pricing, { swarmInputTokens: 1_000_000, swarmOutputTokens: 500_000, swarmAgents: 5, agentInputTokens: 300_000, agentOutputTokens: 150_000, images: 2, mcpCalls: 5, searches: 10, scrapes: 3, nightTime: false, }) console.log(`💰 Estimated workload cost: $${estimate}`) } void main().catch(console.error) ``` </Tab> <Tab title="Rust"> ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde::Deserialize; #[derive(Debug, Deserialize)] struct UsagePricingModel { swarm_completions_agent_cost: f64, swarm_completions_input_cost_per_1m: f64, swarm_completions_output_cost_per_1m: f64, agent_completions_input_cost_per_1m: f64, agent_completions_output_cost_per_1m: f64, agent_completions_img_cost: f64, agent_completions_mcp_cost: f64, search_cost: f64, scrape_cost: f64, night_time_discount: f64, } fn tokens_to_m(tokens: u64) -> f64 { tokens as f64 / 1_000_000.0 } fn estimate_cost(up: &UsagePricingModel) -> f64 { // Example workload; in a real app, pass these as parameters let swarm_input_tokens = 900_000u64; let swarm_output_tokens = 450_000u64; let swarm_agents = 4u64; let agent_input_tokens = 250_000u64; let agent_output_tokens = 125_000u64; let images = 3u64; let mcp_calls = 8u64; let searches = 12u64; let scrapes = 4u64; let night_time = true; let mut cost = 0.0; // Swarm completions (the night-time discount applies only to // swarm input/output token costs, not the per-agent fee) let mut swarm_token_cost = tokens_to_m(swarm_input_tokens) * up.swarm_completions_input_cost_per_1m + tokens_to_m(swarm_output_tokens) * up.swarm_completions_output_cost_per_1m; if night_time { swarm_token_cost *= up.night_time_discount; } cost += swarm_token_cost; cost += swarm_agents as f64 * up.swarm_completions_agent_cost; // Agent completions cost += tokens_to_m(agent_input_tokens) * up.agent_completions_input_cost_per_1m; cost += tokens_to_m(agent_output_tokens) * up.agent_completions_output_cost_per_1m; // Images, MCP, search, scrape cost += images as f64 * up.agent_completions_img_cost; cost += mcp_calls as f64 * up.agent_completions_mcp_cost; cost += searches as f64 * up.search_cost; cost += scrapes as f64 * up.scrape_cost; (cost * 1_000_000.0).round() / 1_000_000.0 } fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let res = client .get("https://api.swarms.world/v1/usage/costs") .header("x-api-key", api_key) .header("Content-Type", "application/json") .send()?; res.error_for_status_ref()?; let json: serde_json::Value = res.json()?; let up: UsagePricingModel = serde_json::from_value(json["usage_pricing"].clone())?; let estimate = estimate_cost(&up); println!("💰 Estimated workload cost: ${:.6}", estimate); Ok(()) } ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "encoding/json" "fmt" "log" "net/http" "os" ) type UsagePricingModel struct { SwarmCompletionsAgentCost float64 `json:"swarm_completions_agent_cost"` SwarmCompletionsInputCostPer1M float64 `json:"swarm_completions_input_cost_per_1m"` SwarmCompletionsOutputCostPer1M float64 `json:"swarm_completions_output_cost_per_1m"` AgentCompletionsInputCostPer1M float64 `json:"agent_completions_input_cost_per_1m"` AgentCompletionsOutputCostPer1M float64 `json:"agent_completions_output_cost_per_1m"` AgentCompletionsImgCost float64 `json:"agent_completions_img_cost"` AgentCompletionsMcpCost float64 `json:"agent_completions_mcp_cost"` SearchCost float64 `json:"search_cost"` ScrapeCost float64 `json:"scrape_cost"` NightTimeDiscount float64 `json:"night_time_discount"` } func tokensToM(tokens int64) float64 { return float64(tokens) / 1_000_000.0 } func estimateCost(up UsagePricingModel) float64 { // Example workload; pass inputs in your own code swarmInputTokens := int64(750000) swarmOutputTokens := int64(350000) swarmAgents := int64(3) agentInputTokens := int64(200000) agentOutputTokens := int64(100000) images := int64(2) mcpCalls := int64(6) searches := int64(8) scrapes := int64(2) nightTime := false cost := 0.0 // Swarm completions (the night-time discount applies only to // swarm input/output token costs, not the per-agent fee) swarmTokenCost := tokensToM(swarmInputTokens)*up.SwarmCompletionsInputCostPer1M + tokensToM(swarmOutputTokens)*up.SwarmCompletionsOutputCostPer1M if nightTime { swarmTokenCost *= up.NightTimeDiscount } cost += swarmTokenCost cost += float64(swarmAgents) * up.SwarmCompletionsAgentCost cost += tokensToM(agentInputTokens) * up.AgentCompletionsInputCostPer1M cost += tokensToM(agentOutputTokens) * up.AgentCompletionsOutputCostPer1M cost += float64(images) * up.AgentCompletionsImgCost cost += float64(mcpCalls) * up.AgentCompletionsMcpCost cost += float64(searches) * up.SearchCost cost += float64(scrapes) * up.ScrapeCost return float64(int64(cost*1_000_000)) / 1_000_000.0 } func main() { apiKey := os.Getenv("SWARMS_API_KEY") if apiKey == "" { log.Fatal("SWARMS_API_KEY environment variable is required") } req, err := http.NewRequest("GET", "https://api.swarms.world/v1/usage/costs", nil) if err != nil { log.Fatal(err) } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { log.Fatalf("unexpected status: %d", resp.StatusCode) } var wrapper struct { UsagePricing UsagePricingModel `json:"usage_pricing"` } if err := json.NewDecoder(resp.Body).Decode(&wrapper); err != nil { log.Fatal(err) } estimate := estimateCost(wrapper.UsagePricing) fmt.Printf("💰 Estimated workload cost: $%.6f\n", estimate) } ``` </Tab> </Tabs> ## When to Use This Pattern * **Pre-flight cost estimation** before running large batch jobs or swarms * **Dashboards and billing UIs** that surface live pricing alongside your own usage metrics * **Guardrails** that block workloads projected to exceed a configured budget # Get Comprehensive Pricing Details Source: https://docs.swarms.ai/docs/examples/examples/pricing-details-basic Fetch and inspect comprehensive pricing details for all Swarms API features Retrieve unified pricing information for all Swarms API usage dimensions from the `/v1/usage/costs` endpoint. This includes token costs, agent costs, search/scrape operations, image pricing, MCP calls, and night-time discount multipliers. <Info> The pricing endpoint is **read-only** and safe to call in automation. Always treat returned values as dynamic and avoid hard-coding pricing in production systems. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def get_pricing_details() -> dict | None: """Fetch comprehensive pricing details.""" resp = requests.get(f"{BASE_URL}/v1/usage/costs", headers=headers) if resp.status_code == 200: return resp.json() print(f"Error: {resp.status_code} - {resp.text}") return None if __name__ == "__main__": data = get_pricing_details() if data: print("✅ Pricing details retrieved successfully!") print(json.dumps(data, indent=2)) usage = data.get("usage_pricing", {}) print("\n--- Key fields ---") print("Swarm input /1M:", usage.get("swarm_completions_input_cost_per_1m")) print("Swarm output /1M:", usage.get("swarm_completions_output_cost_per_1m")) print("Agent image cost:", usage.get("agent_completions_img_cost")) print("Night-time discount:", usage.get("night_time_discount")) ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import 'dotenv/config' const API_KEY = process.env.SWARMS_API_KEY const BASE_URL = 'https://api.swarms.world' async function getPricingDetails() { if (!API_KEY) { throw new Error('SWARMS_API_KEY is not set') } const res = await fetch(`${BASE_URL}/v1/usage/costs`, { method: 'GET', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, }) if (!res.ok) { const body = await res.text() throw new Error(`HTTP ${res.status}: ${body}`) } type UsagePricingModel = { swarm_completions_agent_cost: number swarm_completions_input_cost_per_1m: number swarm_completions_output_cost_per_1m: number agent_completions_input_cost_per_1m: number agent_completions_output_cost_per_1m: number agent_completions_img_cost: number agent_completions_mcp_cost: number search_cost: number scrape_cost: number night_time_discount: number } type PricingDetailsOutput = { usage_pricing: UsagePricingModel timestamp?: string | null } const data = (await res.json()) as PricingDetailsOutput return data } async function main() { try { const data = await getPricingDetails() console.log('✅ Pricing details retrieved successfully!') console.dir(data, { depth: null }) const usage = data.usage_pricing console.log('\n--- Key fields ---') console.log('Swarm completions (input /1M):', usage.swarm_completions_input_cost_per_1m) console.log('Swarm completions (output /1M):', usage.swarm_completions_output_cost_per_1m) console.log('Search cost:', usage.search_cost) console.log('Scrape cost:', usage.scrape_cost) } catch (err) { console.error('Error fetching pricing details:', err) } } void main() ``` </Tab> <Tab title="Rust"> ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde::Deserialize; #[derive(Debug, Deserialize)] struct UsagePricingModel { swarm_completions_agent_cost: f64, swarm_completions_input_cost_per_1m: f64, swarm_completions_output_cost_per_1m: f64, agent_completions_input_cost_per_1m: f64, agent_completions_output_cost_per_1m: f64, agent_completions_img_cost: f64, agent_completions_mcp_cost: f64, search_cost: f64, scrape_cost: f64, night_time_discount: f64, } #[derive(Debug, Deserialize)] struct PricingDetailsOutput { usage_pricing: UsagePricingModel, timestamp: Option<String>, } fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = env::var("SWARMS_API_KEY").expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let res = client .get("https://api.swarms.world/v1/usage/costs") .header("x-api-key", api_key) .header("Content-Type", "application/json") .send()?; if !res.status().is_success() { let body = res.text()?; eprintln!("Error: {} - {}", res.status(), body); return Ok(()); } let data: PricingDetailsOutput = res.json()?; println!("✅ Pricing details retrieved successfully!"); println!("{:#?}", data); println!("\n--- Key fields ---"); println!( "Swarm completions input /1M: {}", data.usage_pricing.swarm_completions_input_cost_per_1m ); println!( "Swarm completions output /1M: {}", data.usage_pricing.swarm_completions_output_cost_per_1m ); println!("Search cost: {}", data.usage_pricing.search_cost); println!("Scrape cost: {}", data.usage_pricing.scrape_cost); Ok(()) } ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "encoding/json" "fmt" "io" "log" "net/http" "os" ) type UsagePricingModel struct { SwarmCompletionsAgentCost float64 `json:"swarm_completions_agent_cost"` SwarmCompletionsInputCostPer1M float64 `json:"swarm_completions_input_cost_per_1m"` SwarmCompletionsOutputCostPer1M float64 `json:"swarm_completions_output_cost_per_1m"` AgentCompletionsInputCostPer1M float64 `json:"agent_completions_input_cost_per_1m"` AgentCompletionsOutputCostPer1M float64 `json:"agent_completions_output_cost_per_1m"` AgentCompletionsImgCost float64 `json:"agent_completions_img_cost"` AgentCompletionsMcpCost float64 `json:"agent_completions_mcp_cost"` SearchCost float64 `json:"search_cost"` ScrapeCost float64 `json:"scrape_cost"` NightTimeDiscount float64 `json:"night_time_discount"` } type PricingDetailsOutput struct { UsagePricing UsagePricingModel `json:"usage_pricing"` Timestamp *string `json:"timestamp"` } func main() { apiKey := os.Getenv("SWARMS_API_KEY") if apiKey == "" { log.Fatal("SWARMS_API_KEY environment variable is required") } req, err := http.NewRequest("GET", "https://api.swarms.world/v1/usage/costs", nil) if err != nil { log.Fatal(err) } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { var bodyBytes []byte bodyBytes, _ = io.ReadAll(resp.Body) log.Fatalf("Error: %d - %s", resp.StatusCode, string(bodyBytes)) } var data PricingDetailsOutput if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { log.Fatal(err) } fmt.Println("✅ Pricing details retrieved successfully!") encoded, _ := json.MarshalIndent(data, "", " ") fmt.Println(string(encoded)) fmt.Println("\n--- Key fields ---") fmt.Println("Swarm completions input /1M:", data.UsagePricing.SwarmCompletionsInputCostPer1M) fmt.Println("Swarm completions output /1M:", data.UsagePricing.SwarmCompletionsOutputCostPer1M) fmt.Println("Search cost:", data.UsagePricing.SearchCost) fmt.Println("Scrape cost:", data.UsagePricing.ScrapeCost) } ``` </Tab> </Tabs> ## Response Shape The endpoint returns a `usage_pricing` object plus a `timestamp`: ```json theme={null} { "usage_pricing": { "swarm_completions_agent_cost": 0.01, "swarm_completions_input_cost_per_1m": 6.5, "swarm_completions_output_cost_per_1m": 18.5, "agent_completions_input_cost_per_1m": 6.5, "agent_completions_output_cost_per_1m": 18.5, "agent_completions_img_cost": 0.25, "agent_completions_mcp_cost": 0.1, "search_cost": 0.04, "scrape_cost": 0.15, "night_time_discount": 0.5 }, "timestamp": "2024-01-01T12:00:00Z" } ``` # Real Estate Investment Memo Swarm Source: https://docs.swarms.ai/docs/examples/examples/real-estate-investment-memo A HierarchicalSwarm that turns a property address and ask price into a one-page institutional investment memo — comps, market context, and financing — directed by an Investment Director. ## What This Example Shows * A `HierarchicalSwarm` with an Investment Director coordinating three worker analysts: Comps, Macro, and Financing * How to feed a property address plus an ask price as the swarm task * How to extract the Director's final memo as the deliverable * A real cost comparison against a broker's analyst writing the same memo <Info> This tutorial uses `HierarchicalSwarm` — the same primitive used by institutional research desks. To run memos on dozens of properties per day or wire this into a Slack bot for your acquisitions team, upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Info> ## Why This Matters Real estate investment committees move slowly because the analyst floor moves slowly. Every deal — even a "let's pass on this one" deal — eats two days of an associate's time to produce a baseline memo: comps from the MLS or CoStar, a paragraph on the submarket, two financing scenarios, and a recommendation. Most of those memos end in a pass. The job is to push the trivial-no and trivial-yes deals through to a decision in minutes so the associate's deep work stays focused on the maybes. A hierarchical swarm with three specialists and a Director does exactly that, and the output reads like an associate wrote it. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Memo Team The Director writes the final one-pager. The three workers each produce one section the Director will weave together. ```python theme={null} INVESTMENT_DIRECTOR_PROMPT = ( "You are the Investment Director at a real estate private equity shop. " "You receive briefs from your Comps Analyst, Macro Analyst, and Financing Analyst. " "Write a single one-page investment memo in this exact structure:\n\n" "PROPERTY: <address>\n" "ASK: $<price>\n\n" "1. RECOMMENDATION: <PURSUE | PASS | PURSUE AT LOWER PRICE>\n" "2. THESIS: <three sentences on why>\n" "3. COMPS SUMMARY: <two sentences synthesizing the Comps brief>\n" "4. MARKET CONTEXT: <two sentences synthesizing the Macro brief>\n" "5. FINANCING: <two sentences synthesizing the Financing brief>\n" "6. KEY RISKS: <three bullets>\n" "7. NEXT STEPS: <one sentence — site visit, LOI, decline>\n\n" "Be decisive. The committee reads the recommendation line first." ) COMPS_ANALYST_PROMPT = ( "You are a Real Estate Comps Analyst. Given a property address and an ask price, " "produce a brief covering: three recent comparable transactions in the same submarket " "(estimated based on your knowledge of the area), price per square foot, cap rate range, " "and whether the ask is at, above, or below market. " "If you do not have specific transaction data, state the typical price-per-sf and cap-rate " "range for that property type and submarket. Keep it under 200 words." ) MACRO_ANALYST_PROMPT = ( "You are a Real Estate Macro Analyst. Given a property address, produce a brief covering: " "submarket fundamentals (population growth, employment, vacancy), the relevant " "interest-rate environment, supply pipeline, and the 18-month demand outlook for the " "property type. Keep it under 200 words." ) FINANCING_ANALYST_PROMPT = ( "You are a Real Estate Financing Analyst. Given a property and an ask price, produce a brief " "covering: two realistic capital-stack options (e.g. 65% LTV agency senior + sponsor equity " "vs. 75% LTV bridge + preferred equity), prevailing interest-rate ranges, estimated " "DSCR at stabilized NOI, and the equity check required for each. Keep it under 200 words." ) def build_memo_swarm(address: str, ask_price: int, property_type: str) -> dict: return { "name": "Real Estate Investment Memo", "description": "Investment Director coordinating Comps, Macro, and Financing analysts.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( f"Produce an institutional investment memo for the following deal:\n\n" f"PROPERTY ADDRESS: {address}\n" f"PROPERTY TYPE: {property_type}\n" f"ASK PRICE: ${ask_price:,}\n\n" "Each analyst writes their brief. The Investment Director then writes the final " "one-page memo with a clear recommendation." ), "agents": [ { "agent_name": "Investment Director", "description": "Director — writes the final one-page memo.", "system_prompt": INVESTMENT_DIRECTOR_PROMPT, "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Comps Analyst", "description": "Comparable transactions and pricing.", "system_prompt": COMPS_ANALYST_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, { "agent_name": "Macro Analyst", "description": "Submarket fundamentals and demand outlook.", "system_prompt": MACRO_ANALYST_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, { "agent_name": "Financing Analyst", "description": "Capital stack, leverage, and DSCR.", "system_prompt": FINANCING_ANALYST_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.4, }, ], } ``` ## Step 3: Run the Memo for One Property Paste in any deal that hits your inbox. Address, ask, property type — that is the entire input the swarm needs. ```python theme={null} def generate_memo(address: str, ask_price: int, property_type: str) -> dict: payload = build_memo_swarm(address, ask_price, property_type) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() result = generate_memo( address="1200 Brickell Avenue, Miami, FL 33131", ask_price=48_500_000, property_type="Class A multifamily (212 units, built 2019)", ) for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:800]) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` ## Step 4: Extract Just the Final Memo For your acquisitions pipeline you only want the Director's one-pager — the analyst briefs are the audit trail. ```python theme={null} def extract_director_memo(result: dict) -> str: for output in result.get("output", []): role = output.get("role", "") if "Investment Director" in role or "Director" in role: content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) return str(content) return "" memo = extract_director_memo(result) print("\n--- COMMITTEE-READY MEMO ---\n") print(memo) # Persist it with open("memo_1200_brickell.md", "w") as f: f.write(memo) ``` <Note> Wire this into a Slack slash command (`/memo <address> <ask>`) and your acquisitions team gets a committee-ready one-pager in under a minute. The analyst briefs sit in the full response if anyone needs to audit a specific section. </Note> ## Real Cost vs. Analyst-Written Memo | Scenario | Cost per memo | Turnaround | Cost per 100 deals screened | | ----------------------------------------------------- | ------------- | ------------ | --------------------------- | | Investment Memo Swarm (4 agents, GPT-4.1) | \~\$0.20 | \~60 seconds | \~\$20 | | Junior analyst writing the memo (fully loaded \$120k) | \~\$700 | 1–2 days | \~\$70,000 | | Outsourced underwriting shop | \~\$300–\$500 | 3–5 days | \~\$30,000–\$50,000 | You are not replacing the deal team — you are letting them screen 10x more deals before committing analyst hours, and giving the IC a structured starting point on every name that does make it through. ## Next Steps * See the [AI Hedge Fund pipeline](/docs/examples/examples/ai-hedge-fund) for the same hierarchical pattern applied to equity research with an overnight batch step * Read the [Supply Chain Hierarchical Swarm](/docs/examples/examples/supply-chain-swarm) to see the same director-and-workers shape applied to ops * Browse [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) for the canonical hierarchical pattern and prompt design tips # Reasoning Agent Types Source: https://docs.swarms.ai/docs/examples/examples/reasoning-agent-types Explore different reasoning agent architectures and their applications Discover the different types of reasoning agents available in the Swarms API. The `/v1/reasoning-agent/types` endpoint provides information about specialized reasoning architectures designed for different problem-solving approaches. <Warning> **Premium Tier Required**: The `/v1/reasoning-agent/completions` endpoint is restricted to Pro, Ultra, and Premium plan subscribers. Free tier users will receive a 403 error. [Upgrade your account](https://swarms.world/platform/account) to access advanced reasoning capabilities. </Warning> <Info> Reasoning agents use advanced techniques like self-consistency, majority voting, and iterative refinement to improve answer quality and reliability. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } def get_reasoning_agent_types(): """Get all available reasoning agent types""" response = requests.get( f"{BASE_URL}/v1/reasoning-agent/types", headers=headers ) if response.status_code == 200: return response.json() else: print(f"Error: {response.status_code} - {response.text}") return None # Get reasoning agent types reasoning_data = get_reasoning_agent_types() if reasoning_data: print("✅ Reasoning agent types retrieved successfully!") print(json.dumps(reasoning_data, indent=2)) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getReasoningAgentTypes() { try { const response = await fetch(`${BASE_URL}/v1/reasoning-agent/types`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Reasoning agent types retrieved successfully!"); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error('Error:', error); return null; } } // Get reasoning agent types getReasoningAgentTypes(); ``` </Tab> <Tab title="cURL"> ```bash theme={null} # Get reasoning agent types curl -X GET "https://api.swarms.world/v1/reasoning-agent/types" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" # Example response: # { # "status": "success", # "agent_types": [ # "reasoning-duo", # "self-consistency", # "ire", # "reasoning-agent", # "consistency-agent", # "ire-agent", # "ReflexionAgent", # "GKPAgent", # "AgentJudge" # ] # } ``` </Tab> </Tabs> ## Reasoning Agent Type Comparison The `/v1/reasoning-agent/types` endpoint currently returns 9 reasoning agent types: | Type | Description | Best For | Samples | Quality Focus | | ----------------------- | ------------------------------------------------------------------------------- | --------------------------------------- | -------- | ---------------- | | **reasoning-agent** | Basic reasoning with structured thinking | Simple reasoning tasks | 1 | Balanced | | **reasoning-duo** | Two agents with different approaches | Comparative analysis | 2 | Diversity | | **self-consistency** | Multiple samples for consistency checking | High-stakes decisions | 3-5 | Consistency | | **ire** / **ire-agent** | Iterative refinement through multiple passes | Complex problem-solving | Variable | Accuracy | | **consistency-agent** | Focus on logical consistency | Mathematical/logical problems | 3 | Logical rigor | | **ReflexionAgent** | Self-critiques and revises its own output across iterations | Tasks that benefit from self-correction | Variable | Self-improvement | | **GKPAgent** | Generated Knowledge Prompting — generates supporting knowledge before answering | Knowledge-intensive tasks | Variable | Grounding | | **AgentJudge** | Evaluates and scores candidate outputs | Output evaluation / grading | Variable | Evaluation | ## Request Parameters Send these fields in the JSON body of `POST /v1/reasoning-agent/completions` (the `ReasoningAgentSpec` schema): | Parameter | Type | Default | Description | | --------------------- | --------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `agent_name` | `string` | `"reasoning-agent"` | The unique name assigned to the reasoning agent | | `description` | `string` | `"A reasoning agent that can answer questions and help with tasks."` | A detailed explanation of the reasoning agent's purpose and capabilities | | `model_name` | `string` | `"claude-sonnet-4-20250514"` | The name of the AI model that the reasoning agent will utilize | | `system_prompt` | `string` | `None` | The initial instruction or context provided to the reasoning agent | | `max_loops` | `integer` | `1` | Maximum number of times the agent repeats its task (ignored for `ire` / `ire-agent`, which manage iteration internally) | | `swarm_type` | `string` | `"reasoning_duo"` | The reasoning agent type — pass one of the 9 values listed above | | `num_samples` | `integer` | `1` | The number of samples to generate for the reasoning agent | | `output_type` | `string` | `"dict-all-except-first"` | Accepted for schema compatibility but **ignored by the server** — responses are always returned in `dict-all-except-first` format | | `num_knowledge_items` | `integer` | `None` | The number of knowledge items to use for the reasoning agent | | `memory_capacity` | `integer` | `None` | The memory capacity for the reasoning agent | | `task` | `string` | `None` | The task to be completed by the reasoning agent | <Note> The schema default for `swarm_type` is the underscore spelling `"reasoning_duo"`, which is not itself one of the 9 accepted values — the enum only contains the hyphenated `"reasoning-duo"`. If you set `swarm_type` explicitly, use one of the 9 hyphenated/listed values above; the underscore form is rejected. </Note> ## Response Format `POST /v1/reasoning-agent/completions` returns a `ReasoningAgentCompletionOutput` object: | Field | Type | Description | | ------------ | -------- | ---------------------------------------------------------------------------- | | `job_id` | `string` | Unique identifier for the reasoning agent run | | `status` | `string` | Status of the run, `"success"` on completion | | `outputs` | `any` | The output generated by the reasoning agent — shape varies by reasoning type | | `timestamp` | `string` | ISO-formatted timestamp of when the run was executed | | `agent_name` | `string` | Name of the agent | | `agent_type` | `string` | Type of the agent (the `swarm_type` used) | | `agent_id` | `string` | Unique identifier for the agent instance | | `usage` | `object` | Token usage: `input_tokens`, `output_tokens`, `total_tokens` | ## Usage Examples <Tabs> <Tab title="Basic Reasoning Agent"> ```python theme={null} payload = { "agent_name": "Basic Reasoner", "model_name": "gpt-4.1", "system_prompt": "You are a logical reasoning assistant.", "max_loops": 1, "swarm_type": "reasoning-agent", "num_samples": 1, "task": "Solve this logic puzzle: If all bloops are razzes and some razzes are fizzles, are all bloops fizzles?" } ``` </Tab> <Tab title="Self-Consistency Agent"> ```python theme={null} payload = { "agent_name": "Consistent Reasoner", "model_name": "gpt-4.1", "system_prompt": "You are a reasoning agent that values consistency.", "max_loops": 1, "swarm_type": "self-consistency", "num_samples": 3, "task": "Determine the most logical conclusion from these premises: All humans are mortal. Socrates is human. Therefore..." } ``` </Tab> <Tab title="Iterative Refinement Agent"> ```python theme={null} payload = { "agent_name": "Refinement Agent", "model_name": "gpt-4.1", "system_prompt": "You are an agent that improves through iteration.", "swarm_type": "ire", # manages its refinement iterations internally; max_loops is ignored "num_samples": 2, "task": "Design a more efficient algorithm for sorting a list of numbers." } ``` </Tab> <Tab title="Reasoning Duo"> ```python theme={null} payload = { "agent_name": "Dual Reasoner", "model_name": "gpt-4.1", "system_prompt": "You are a dual reasoning system.", "max_loops": 1, "swarm_type": "reasoning-duo", "num_samples": 2, "task": "Debate the pros and cons of renewable energy adoption." } ``` </Tab> </Tabs> ## Advanced Configuration <Tabs> <Tab title="Custom Sample Count"> ```python theme={null} payload = { "agent_name": "High Consistency Agent", "model_name": "gpt-4.1", "max_loops": 1, "swarm_type": "self-consistency", "num_samples": 5, # Higher sample count for better consistency "task": "Analyze the potential risks of artificial general intelligence." } ``` </Tab> <Tab title="Multi-Iteration Reasoning"> ```python theme={null} payload = { "agent_name": "Deep Analysis Agent", "model_name": "gpt-4.1", "max_loops": 5, # Multiple refinement iterations "swarm_type": "ReflexionAgent", "num_samples": 3, "task": "Develop a comprehensive business strategy for a tech startup." } ``` </Tab> <Tab title="Knowledge Integration"> ```python theme={null} payload = { "agent_name": "Knowledge Agent", "model_name": "gpt-4.1", "max_loops": 1, "swarm_type": "consistency-agent", "num_samples": 3, "num_knowledge_items": 5, # Include knowledge base "memory_capacity": 10, "task": "Integrate these research findings into a coherent theory." } ``` </Tab> </Tabs> ## Output Format <Note> The `output_type` request field is accepted by the schema but **ignored by the server** — the reasoning agent always runs with `dict-all-except-first`, which returns every reasoning step after the initial prompt as role/content entries in the `outputs` field. Passing `"dict"`, `"list"`, or `"final"` validates but has no effect on the response. </Note> ```python theme={null} result = response.json() # outputs is a list of role/content entries for most reasoning types outputs = result["outputs"] if isinstance(outputs, list): for entry in outputs: print(f"{entry.get('role', '')}: {entry.get('content', '')}") else: # Some types (e.g. AgentJudge) return a plain string print(outputs) ``` ## Performance Optimization <Tabs> <Tab title="Quality vs Speed"> ```python theme={null} def optimize_reasoning_config(task_complexity, time_constraint): """Optimize reasoning configuration based on requirements""" if time_constraint == "fast": return { "swarm_type": "reasoning-agent", "num_samples": 1, "max_loops": 1, "model_name": "gpt-4.1-mini" } elif task_complexity == "high": return { "swarm_type": "ReflexionAgent", "num_samples": 5, "max_loops": 3, "model_name": "gpt-4.1" } else: # balanced return { "swarm_type": "self-consistency", "num_samples": 3, "max_loops": 1, "model_name": "gpt-4.1" } ``` </Tab> <Tab title="Cost Optimization"> ```python theme={null} def optimize_reasoning_cost(budget, quality_requirement): """Optimize for cost while maintaining quality""" if budget < 0.1: return { "swarm_type": "reasoning-agent", "model_name": "gpt-4.1-mini", "num_samples": 1 } elif quality_requirement == "high": return { "swarm_type": "self-consistency", "model_name": "gpt-4.1", "num_samples": 3 } else: return { "swarm_type": "reasoning-duo", "model_name": "gpt-4.1-mini", "num_samples": 2 } ``` </Tab> </Tabs> ## Use Cases by Domain <Tabs> <Tab title="Scientific Research"> ```python theme={null} payload = { "agent_name": "Scientific Reasoner", "swarm_type": "ire", "num_samples": 3, "task": "Design an experiment to test the hypothesis that X causes Y." } ``` </Tab> <Tab title="Business Strategy"> ```python theme={null} payload = { "agent_name": "Strategy Consultant", "swarm_type": "reasoning-duo", "num_samples": 2, "task": "Evaluate three potential market entry strategies for our product." } ``` </Tab> <Tab title="Legal Analysis"> ```python theme={null} payload = { "agent_name": "Legal Analyst", "swarm_type": "self-consistency", "num_samples": 5, "task": "Analyze the legal implications of this contract clause." } ``` </Tab> <Tab title="Technical Problem Solving"> ```python theme={null} payload = { "agent_name": "Technical Expert", "swarm_type": "consistency-agent", "num_samples": 3, "task": "Debug this software issue and propose a solution." } ``` </Tab> </Tabs> ## Best Practices ### Configuration Guidelines 1. **Task Complexity**: Match reasoning type to task complexity 2. **Sample Count**: Use more samples for high-stakes decisions 3. **Iteration Count**: Increase iterations for complex refinement 4. **Model Selection**: Choose appropriate model based on requirements ### Quality Assurance 1. **Consistency Checking**: Use self-consistency for critical decisions 2. **Diverse Perspectives**: Leverage reasoning-duo for balanced analysis 3. **Iterative Improvement**: Apply IRE for complex problem-solving 4. **Validation**: Always validate reasoning outputs ### Performance Considerations 1. **Resource Usage**: Monitor token usage and costs 2. **Response Time**: Balance quality with response speed 3. **Scalability**: Consider parallel processing for multiple tasks 4. **Caching**: Cache reasoning results when appropriate ### Error Handling 1. **Fallback Logic**: Implement fallback to simpler reasoning types 2. **Timeout Handling**: Set appropriate timeouts for long-running tasks 3. **Result Validation**: Validate reasoning outputs for correctness 4. **Logging**: Log reasoning processes for debugging # Reasoning Agents for Hard Analytical Problems Source: https://docs.swarms.ai/docs/examples/examples/reasoning-agents-tutorial Solve a competition-grade multi-step accrual accounting problem end-to-end with a reasoning agent — the same task a normal LLM call hallucinates on. ## What This Example Shows * One real, hard analytical problem solved end-to-end with `POST /v1/reasoning-agent/completions` * Why a normal agent call hallucinates on this and how `swarm_type: "self-consistency"` fixes it * How to tune `num_samples` and `max_loops` for the depth-vs-cost tradeoff on a single high-stakes question * How to read the structured `outputs` payload (returned in `dict-all-except-first` format) to extract the answer programmatically * A direct side-by-side: same task, plain agent vs. reasoning agent, real failure modes <Warning> The Reasoning Agent endpoint (`POST /v1/reasoning-agent/completions`) is a **premium-only** feature available on Pro, Ultra, and Premium plans. Free tier keys receive a 403. [Upgrade your account](https://swarms.world/platform/account) to unlock self-consistency, iterative refinement, and multi-sample deliberation. </Warning> ## Why This Matters Some questions look like they should be a one-shot LLM call but aren't. A multi-step accrual reconciliation. A cross-jurisdiction tax allocation. A logic puzzle with five interlocking constraints. An algorithm correctness proof. These are problems where a wrong-looking-but-confident answer is worse than no answer, because nobody downstream has the time to re-derive the calculation by hand. A plain `gpt-4` call will produce a single deterministic chain of thought and confidently miscount the deferred revenue. A reasoning agent samples multiple chains, votes on the convergent answer, and surfaces the disagreement when the chains don't converge — which is exactly the signal you need to escalate a question to a human. The job done isn't "smarter LLM," it's **calibrated confidence on hard analytical work**. ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } ``` ## Step 2: The Problem This is the kind of problem a controller would hand to a senior associate. It is solvable in closed form, but every step compounds the next, so a single dropped assumption produces a confidently wrong number. ```python theme={null} problem = """ A SaaS company sells a 24-month enterprise subscription on October 1, 2024 for a total contract value of $480,000, billed annually in advance. Contract terms: - The first $240,000 is billed and collected on October 1, 2024, covering October 1, 2024 through September 30, 2025. - The second $240,000 is billed and collected on October 1, 2025, covering October 1, 2025 through September 30, 2026. - The customer is granted a one-time 5% discount that applies to the SECOND year only, reducing the second-year invoice (and cash collected) to $228,000. The discount is contractual at inception and is not a separate performance obligation. - Revenue is recognized ratably on a straight-line basis under ASC 606. - The company's fiscal year ends December 31. Required: 1. What is the total transaction price under ASC 606 at contract inception? 2. What is the monthly revenue recognition amount? 3. As of December 31, 2024, what is (a) revenue recognized year-to-date, (b) deferred revenue on the balance sheet, and (c) contract asset or contract liability if any? 4. As of December 31, 2025, what is (a) revenue recognized in fiscal 2025, (b) deferred revenue on the balance sheet, and (c) accounts receivable if any? Show every step of the calculation. Return a final JSON object with keys: transaction_price, monthly_revenue, dec_2024 (with sub-keys revenue_ytd, deferred_revenue, contract_asset_or_liability), and dec_2025 (with sub-keys revenue_fy2025, deferred_revenue, accounts_receivable). """.strip() ``` <Note> The trick step is question 3. The \$240k cash collected in Oct 2024 covers months 1-12 of the contract, but the transaction price is allocated over the full 24 months at \$19,500/month (not \$20,000/month), so YTD recognition through Dec 31, 2024 is **3 months × \$19,500 = \$58,500**, not \$60,000. The remainder of the \$240k cash sits as deferred revenue. A plain LLM call will frequently compute \$20,000/month and miss the discount allocation. </Note> ## Step 3: First — Try It With a Plain Agent (for Comparison) Run the exact same problem through the standard agent completion endpoint. Keep this number — you'll compare against the reasoning agent's answer. ```python theme={null} plain_payload = { "agent_config": { "agent_name": "Accounting-Plain", "description": "Standard accounting agent (single chain of thought).", "system_prompt": ( "You are a CPA. Solve accounting problems carefully under ASC 606. " "Return the final answer as JSON." ), "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 4000, }, "task": problem, } plain_response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=plain_payload, timeout=300, ) plain_response.raise_for_status() print("=" * 60) print("PLAIN AGENT — single chain of thought") print("=" * 60) print(json.dumps(plain_response.json(), indent=2)[:1500]) ``` In practice on this problem the plain agent will produce a confident but wrong allocation roughly **40-60% of the time** — most often by computing \$20,000/month for the first year (ignoring that the \$12,000 discount must be allocated across all 24 months under ASC 606). ## Step 4: Now Solve It With a Reasoning Agent Switch to `/v1/reasoning-agent/completions` with `swarm_type: "self-consistency"`. The agent runs `num_samples` independent reasoning chains and votes on the convergent answer. ```python theme={null} reasoning_payload = { "agent_name": "Accrual-Reasoner", "description": ( "ASC 606 revenue recognition specialist with self-consistency " "deliberation across multiple independent reasoning chains." ), "model_name": "claude-sonnet-4-20250514", "system_prompt": ( "You are a CPA specializing in ASC 606 revenue recognition. " "When solving a problem, derive the total transaction price first, " "then allocate ratably across the full performance period. Show every " "step. The final line of your response MUST be a single JSON object " "containing the requested fields." ), "swarm_type": "self-consistency", "num_samples": 5, "max_loops": 1, "output_type": "dict-all-except-first", "task": problem, } reasoning_response = requests.post( f"{BASE_URL}/v1/reasoning-agent/completions", headers=headers, json=reasoning_payload, timeout=600, ) reasoning_response.raise_for_status() result = reasoning_response.json() print("=" * 60) print("REASONING AGENT — self-consistency, 5 samples") print("=" * 60) print(json.dumps(result, indent=2)[:3000]) ``` The response (`result` above) is a `ReasoningAgentCompletionOutput` object with these top-level fields: | Field | Type | Description | | ------------ | -------- | --------------------------------------------------------------------------------- | | `job_id` | `string` | Unique identifier for the reasoning agent run | | `status` | `string` | Run status, `"success"` on completion | | `outputs` | `any` | The reasoning output — shape varies by `swarm_type` and `output_type` (see below) | | `timestamp` | `string` | ISO-formatted timestamp of when the run was executed | | `agent_name` | `string` | Name of the agent (the `agent_name` you passed in the request) | | `agent_type` | `string` | The `swarm_type` used for this run, e.g. `"self-consistency"` | | `agent_id` | `string` | Unique identifier for the agent instance | | `usage` | `object` | Token usage: `input_tokens`, `output_tokens`, `total_tokens`, `total_cost` | `outputs` is where the reasoning content lives. The API returns it in `dict-all-except-first` format (the `output_type` default) — a conversation-style structure of role/content entries covering every reasoning step after the initial prompt, ending with the convergent final answer that Step 5 below extracts. ## Step 5: Extract the Answer With the default `output_type` (`dict-all-except-first`), `outputs` contains the per-sample reasoning chains with the convergent final answer last. The convergent answer is the one to trust; the per-sample chains are the audit trail. ```python theme={null} # outputs is a list of role/content entries (dict-all-except-first format); # the convergent final answer is the last entry's content outputs = result.get("outputs", []) if isinstance(outputs, list) and outputs: blob = str(outputs[-1].get("content", "")) else: blob = json.dumps(outputs) # The system prompt asked for a single JSON object as the final line — # scan the content from the end for the first line that parses final = None for line in reversed(blob.splitlines()): line = line.strip().strip("`").strip() # tolerate a fenced code block if line.startswith("{") and line.endswith("}"): try: final = json.loads(line) break except json.JSONDecodeError: continue print("\nExtracted answer:") print(json.dumps(final, indent=2)) # Sanity-check the structure expected = { "transaction_price": 468_000, "monthly_revenue": 19_500, "dec_2024": { "revenue_ytd": 58_500, # 3 months "deferred_revenue": 181_500, # 240,000 cash - 58,500 recognized "contract_asset_or_liability": "contract liability (deferred revenue)", }, "dec_2025": { "revenue_fy2025": 234_000, # 12 months "deferred_revenue": 175_500, # carry-forward math }, } print("\nExpected key figures:") print(json.dumps(expected, indent=2)) ``` <Note> \$468,000 transaction price = \$480,000 contract value − \$12,000 discount, allocated ratably over 24 months = **\$19,500/month**. Three months in fiscal 2024 = \$58,500 recognized; the rest of the first \$240,000 cash collected sits as a contract liability. </Note> ## Step 6: Tuning the Depth Knob `num_samples` is the deliberation budget. Use this table to pick a setting: | `num_samples` | When to use | Cost multiplier | | ------------- | -------------------------------------------------------------------------------------- | --------------- | | 1 | Smoke testing, prototyping | 1x | | 3 | Default for hard analytical work | \~3x | | 5 | High-stakes single-answer questions (this example, legal opinions, regulatory filings) | \~5x | | 7-10 | Convergence diagnostics — if 7 samples still disagree, escalate to a human | \~7-10x | The right read on convergence: if all 5 samples produce the same final JSON, ship the answer. If 4-of-5 agree, ship with a flag. If 3-of-5 or worse, the problem is genuinely ambiguous and you need a human in the loop — that **signal** is what you're paying for, not just the answer. ## Picking the Right `swarm_type` | `swarm_type` | What it does | Best for this kind of work | | ------------------- | ---------------------------------------------------- | ---------------------------------------- | | `reasoning-agent` | Single chain with structured thinking | Quick checks, drafts | | `self-consistency` | N independent chains, vote on convergence | **This example, calibrated answers** | | `ire` | Iterative refinement — each loop critiques the prior | Algorithmic / proof-style problems | | `reasoning-duo` | Two agents debate two approaches | Contrarian framing, strategy reviews | | `consistency-agent` | Logical-consistency focused | Pure math and logic puzzles | | `ReflexionAgent` | Self-critiques and revises its own output | Drafts that improve with self-correction | | `GKPAgent` | Generates supporting knowledge before answering | Knowledge-intensive questions | | `AgentJudge` | Evaluates and scores candidate outputs | Grading another agent's answer | For accrual accounting, legal interpretation, and financial calculation work, `self-consistency` is the right default — the failure mode is "confidently wrong on one chain," and voting across chains is the specific antidote. <Note> The full list of supported values is returned by `GET /v1/reasoning-agent/types`: `reasoning-duo`, `self-consistency`, `ire`, `reasoning-agent`, `consistency-agent`, `ire-agent`, `ReflexionAgent`, `GKPAgent`, `AgentJudge`. For the `ire` / `ire-agent` types the API manages iteration internally and ignores `max_loops`. </Note> ## Cost vs. Hiring a Senior Associate Concrete numbers for a high-stakes analytical question (the accrual problem above): | Approach | Time to answer | Cost | Calibrated confidence? | | ------------------------------------------------------------------ | --------------- | ----------------------------- | ----------------------------------------------- | | Senior accounting associate | 25-40 min | \~\$80-130 fully-loaded labor | Yes (but variable) | | Plain `gpt-4` call | \~6 sec | \~\$0.05 | **No** — single confident chain, fails \~40-60% | | **Reasoning agent (self-consistency, 5 samples, Claude Sonnet 4)** | **\~30-60 sec** | **\~\$0.20-0.50** | **Yes** — convergence is the signal | Use the reasoning agent for the questions where being wrong is expensive — accruals that hit a 10-K, tax allocations on a large deal, contract interpretations, complex underwriting. Use a plain agent for everything else. The reasoning agent is **\~250x cheaper than the associate** *and* gives you a convergence signal the associate can't, because a single human only has one chain of thought. <Warning> A reasoning agent producing 5-of-5 convergence is strong evidence the answer is correct under the given assumptions. It is **not** evidence the assumptions are correct. For anything that hits a regulated filing, the calculated answer goes to a licensed human reviewer who validates the inputs. </Warning> ## Next Steps * [Graph Workflows for Production Pipelines](/docs/examples/examples/graph-workflows-production) — embed a reasoning agent as one node in a larger production DAG * [Reasoning Agent Types](/docs/examples/examples/reasoning-agent-types) — full catalog of `swarm_type` options and their tradeoffs # Round Robin Example Source: https://docs.swarms.ai/docs/examples/examples/round-robin Build a collaborative research team with RoundRobin ## Collaborative Research Team with Round-Robin Turns This example demonstrates how to use RoundRobin to facilitate collaborative discussion where agents take turns in a fixed rotation and build on each other's contributions — perfect for brainstorming, research synthesis, and cross-functional planning. ### Step 1: Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Set it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import json import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define the Research Team Create a team of domain experts who will take turns contributing their perspective. Each agent sees the full conversation history and builds on what others have said: ```python theme={null} def run_roundtable(topic: str, max_loops: int = 1) -> dict: """Run a collaborative round-robin research discussion.""" swarm_config = { "name": "Research Roundtable", "description": "Collaborative research with round-robin agent turns", "swarm_type": "RoundRobin", "task": topic, "agents": [ { "agent_name": "Industry Researcher", "description": "Gathers market data and industry trends", "system_prompt": "You are an industry researcher. Provide data-driven market analysis, cite specific numbers and trends, and identify key players. Build on insights from other team members when available.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Technology Analyst", "description": "Evaluates technical landscape and innovation", "system_prompt": "You are a technology analyst. Assess the technical landscape, evaluate emerging technologies, and identify innovation opportunities. Reference and build upon the research data shared by other team members.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 }, { "agent_name": "Strategy Advisor", "description": "Synthesizes insights into actionable strategy", "system_prompt": "You are a strategy advisor. Synthesize insights from the team into actionable strategic recommendations. Identify risks, opportunities, and provide a prioritized roadmap. Reference specific points made by other team members.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5 } ], "max_loops": max_loops } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=180 ) return response.json() ``` ### Step 4: Run the Roundtable ```python theme={null} # Define the research topic topic = """ Analyze the emerging autonomous AI agent market. Cover the current state of the technology, major players and their approaches, enterprise adoption barriers, and the most promising near-term use cases. Provide actionable insights for a startup considering entering this space. """ # Run the roundtable discussion result = run_roundtable(topic) # Display the collaborative discussion for output in result.get("output", []): agent = output["role"] content = output["content"] print(f"\n{'='*60}") print(f"{agent}") print(f"{'='*60}") # Handle content as string or list if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:800] + "...") ``` **Expected Output:** ``` ============================================================ Industry Researcher ============================================================ ## Autonomous AI Agent Market Analysis ### Market Overview The autonomous AI agent market reached an estimated $4.2B in 2024 and is projected to grow at 45% CAGR through 2028. Key segments include: - Developer tools & coding agents (35% of market) - Customer service automation (28%) - Enterprise workflow agents (22%) - Research & analysis agents (15%) ### Major Players - **OpenAI** (GPT-based agents, Assistants API) - **Anthropic** (Claude, tool use framework) - **Google** (Gemini agents, Vertex AI) - **Startups**: Cognition (Devin), Adept, Induced AI, CrewAI, Swarms ### Enterprise Adoption Current penetration: ~12% of Fortune 500 in production... ============================================================ Technology Analyst ============================================================ Building on the Industry Researcher's market data, let me assess the technical landscape: ### Core Technology Stack The agent frameworks broadly fall into three categories: 1. **Single-agent loops** (ReAct, function calling) — mature but limited 2. **Multi-agent orchestration** (Swarms, CrewAI, AutoGen) — growing fast 3. **Code-generation agents** (Devin, Cursor) — highest enterprise demand ### Key Technical Differentiators Drawing from the market segments identified above: - Tool use reliability (currently 85-92% accuracy) - Context window management for long-running tasks - Multi-step planning and self-correction capabilities - Sandboxed execution environments for safety... ============================================================ Strategy Advisor ============================================================ Synthesizing the market data from our Industry Researcher and the technical assessment from our Technology Analyst, here are my strategic recommendations: ### Entry Strategy (Priority Order) 1. **Target the multi-agent orchestration gap** — As noted, this segment is growing fastest at 45% CAGR, and tool use reliability (85-92%) leaves room for differentiation through better orchestration 2. **Focus on enterprise workflow agents** — The 22% market share with only 12% Fortune 500 penetration signals massive headroom 3. **Build on open-source adoption** — CrewAI and Swarms have proven the community-first model works for developer tools ### Key Risks - Commoditization risk as foundation model providers add native agent features - Enterprise security and compliance requirements add 6-12 months to sales cycles... ``` ### Step 5: Multi-Loop Refinement (Optional) Run multiple rounds so agents can iterate on each other's contributions: ```python theme={null} # Run 2 loops — agents go around twice, refining their analysis each time deep_result = run_roundtable( topic="Evaluate the competitive positioning of Anthropic vs OpenAI vs Google in the enterprise AI market. Assess technical capabilities, pricing strategy, ecosystem lock-in, and likely market share in 3 years.", max_loops=2 ) # Show the final contributions after 2 rounds of refinement for output in deep_result.get("output", []): print(f"\n{output['role']}:") content = output["content"] if isinstance(content, list): content = ' '.join(str(item) for item in content) print(str(content)[:600] + "...") ``` <Note> RoundRobin creates a collaborative dynamic where each agent sees the full conversation history and naturally builds on prior contributions. Agent order is the same on every loop, and every agent gets exactly one turn per loop. Use `max_loops` > 1 when you want the team to iteratively refine their analysis across multiple rounds. </Note> # Search-Enabled Agents Source: https://docs.swarms.ai/docs/examples/examples/search-enabled Agents with web search capabilities for real-time information retrieval The Swarms API supports search-enabled agents that can access real-time web information using integrated search capabilities. This allows agents to provide up-to-date answers and research current topics. <Info> Enable web search by setting `"tools_enabled": ["auto_search"]` in your request to access current information and real-time data. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Research Assistant", "description": "AI assistant with web search capabilities", "system_prompt": "You are a research assistant that can search the web for current information.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.7 }, "task": "What are the latest developments in quantum computing?", "tools_enabled": ["auto_search"] } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) result = response.json() print(result['outputs']) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const payload = { agent_config: { agent_name: "News Analyst", description: "Current events and news analysis specialist", system_prompt: "You are a news analyst who researches current events and provides analysis.", model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.6 }, task: "What are the latest headlines about artificial intelligence regulations?", tools_enabled: ["auto_search"] }; fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { console.log("Search Results:", data.outputs); }) .catch(error => console.error('Error:', error)); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Research Assistant", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.7 }, "task": "What are the latest developments in quantum computing?", "tools_enabled": ["auto_search"] }' ``` </Tab> </Tabs> ## Search Integration When `tools_enabled` includes `"auto_search"`, the agent can: * Access real-time web information * Search for current news and developments * Verify facts with up-to-date sources * Provide contextually relevant information * Cite sources for transparency ## Use Cases ### Current Events Research ```python theme={null} payload = { "agent_config": { "agent_name": "Current Events Researcher", "description": "Specializes in current events and breaking news", "system_prompt": "You research current events and provide factual summaries.", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "Summarize the latest developments in climate change policy.", "tools_enabled": ["auto_search"] } ``` ### Market Research ```python theme={null} payload = { "agent_config": { "agent_name": "Market Researcher", "description": "Market trends and competitive analysis", "system_prompt": "You analyze market trends and provide competitive intelligence.", "model_name": "gpt-4.1", "max_tokens": 4096 }, "task": "What are the current market trends in electric vehicles?", "tools_enabled": ["auto_search"] } ``` ### Technical Research ```python theme={null} payload = { "agent_config": { "agent_name": "Technical Researcher", "description": "Research latest technical developments", "system_prompt": "You research technical topics and explain complex concepts.", "model_name": "gpt-4.1", "max_tokens": 4096 }, "task": "What are the latest advancements in machine learning algorithms?", "tools_enabled": ["auto_search"] } ``` ### Product Research ```python theme={null} payload = { "agent_config": { "agent_name": "Product Researcher", "description": "Product reviews and comparisons", "system_prompt": "You research products and provide detailed comparisons.", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "Compare the latest smartphones from different manufacturers.", "tools_enabled": ["auto_search"] } ``` ## Search Quality Control ### Source Verification ```python theme={null} payload = { "agent_config": { "agent_name": "Fact Checker", "description": "Verifies information with reliable sources", "system_prompt": "You verify facts and cite reliable sources.", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "Verify the accuracy of recent claims about renewable energy adoption rates.", "tools_enabled": ["auto_search"] } ``` ### Recent Information Priority ```python theme={null} payload = { "agent_config": { "agent_name": "Recent News Analyst", "description": "Focuses on the most recent information", "system_prompt": "You prioritize the most recent and relevant information.", "model_name": "gpt-4.1", "max_tokens": 2048 }, "task": "What are the most recent developments in space exploration from the past week?", "tools_enabled": ["auto_search"] } ``` ## Advanced Search Configuration ### Combined with Conversation History ```python theme={null} payload = { "agent_config": { "agent_name": "Research Conversationalist", "description": "Maintains context while researching", "system_prompt": "You maintain conversation context while researching current information.", "model_name": "gpt-4.1", "max_tokens": 4096 }, "task": "Based on our previous discussion about AI, what are the latest regulatory developments?", "tools_enabled": ["auto_search"], "history": { "previous_context": { "role": "user", "content": "Tell me about AI safety concerns" }, "ai_response": { "role": "assistant", "content": "AI safety involves alignment, robustness, and ethical considerations..." } } } ``` ## Best Practices 1. **Specific Queries**: Ask specific questions for better search results 2. **Time Sensitivity**: Specify time frames for time-sensitive topics 3. **Source Quality**: Request verification from reliable sources when needed 4. **Context Preservation**: Use conversation history for follow-up questions 5. **Cost Awareness**: Search-enabled agents use additional tokens ## Cost Considerations * **Search Operations**: Additional costs for web search access * **Token Usage**: Increased token consumption for search results processing * **Quality Trade-off**: Balance search quality with cost efficiency ## Error Handling ```python theme={null} try: response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60 ) if response.status_code == 200: result = response.json() print("Search Results:", result['outputs']) elif response.status_code == 429: print("Rate limit exceeded for search operations") else: print(f"Search error: {response.status_code} - {response.text}") except requests.exceptions.Timeout: print("Search request timed out") except requests.exceptions.ConnectionError: print("Failed to connect to search service") except Exception as e: print(f"Search integration error: {e}") ``` ## Search Result Format Search-enabled agents return the standard `/v1/agent/completions` response shape. The agent's answer (with any web-sourced facts woven into the text) appears in `outputs`. The search tool's \$0.04 fee is deducted from your credits as a separate charge — it is not included in the `usage.total_cost` field, which covers token and image costs only: ```json theme={null} { "job_id": "agent-09a9c0f9ba19419abf64f5538b4b7d59", "success": true, "name": "Research Assistant", "outputs": [ { "role": "Research Assistant", "content": "Comprehensive analysis based on current web data...", "timestamp": "2026-02-05T00:58:15.121915", "message_id": "85b70f9d-e281-4a98-b9ad-5a2d39f8ffcb" } ], "usage": { "input_tokens": 150, "output_tokens": 300, "total_tokens": 450, "img_cost": 0.0, "total_cost": 0.006525 }, "timestamp": "2026-02-05T00:58:15.252392+00:00" } ``` ## Rate Limiting Search operations have no extra rate limits of their own; they count against your account's normal request limits (free tier): * **Per Minute**: 100 requests * **Per Hour**: 350 requests * **Per Day**: 1200 requests Implement exponential backoff for rate limit handling: ```python theme={null} import time def search_with_backoff(payload, max_retries=3): for attempt in range(max_retries): response = requests.post(f"{BASE_URL}/v1/agent/completions", json=payload, headers=headers) if response.status_code == 429: wait_time = 2 ** attempt # Exponential backoff print(f"Rate limited, waiting {wait_time} seconds...") time.sleep(wait_time) continue return response raise Exception("Max retries exceeded for search request") ``` # SEC Filing Triage Pipeline: 10-K, 10-Q, and 8-K Diffs Against Prior Period Source: https://docs.swarms.ai/docs/examples/examples/sec-filing-triage-pipeline A SequentialWorkflow that ingests EDGAR filings, extracts the load-bearing sections, diffs them against the prior period, and lands a materiality-scored memo on every name in the book before the open. Every morning by 7am ET, every new 10-Q for every name in the book has a materiality-scored diff memo waiting. ## What This Example Shows * A `SequentialWorkflow` that pipes a single EDGAR accession number through classification, section extraction, diffing, scoring, and memo generation * Five OpenAI-format **function tools** wired into the agents: EDGAR fetch, MD\&A parser, Risk Factors extractor, section differ, and a materiality scorer * Real **EDGAR ingestion** including the SEC-mandated `User-Agent` header — no scraping, no hand-built parsers downstream * A **diff-against-prior** core: the pipeline only surfaces what changed versus the previous comparable filing (10-Q vs. prior 10-Q, 10-K vs. prior 10-K, 8-K vs. nothing) * A **materiality score** (0-100) attached to every delta so analysts read top-of-stack, not chronologically * An overnight **batch run** of 30-50 filings per portfolio per day against `/v1/swarm/batch/completions` — a premium-only endpoint (Pro, Ultra, or Premium tier) <Info> The `/v1/swarm/batch/completions` endpoint used in Step 5 is a premium feature — a Pro, Ultra, or Premium tier key unlocks it, and all three share the same request limits. Upgrade for the parallel execution and observability (per-filing cost, per-agent token counts, structured run logs) you need to actually trust this in production. Manage your plan at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Info> ## Why This Matters Analysts do not read 10-Qs — they skim them for what changed. A 90-page Q3 filing is 87 pages of boilerplate, copy-pasted disclaimers, and last quarter's text, plus 3 pages of new language buried somewhere in MD\&A, Risk Factors, or the footnotes that actually moves the thesis. The job of this pipeline is not to summarize filings; it is to throw away the 87 pages of unchanged text, isolate the new language, score how thesis-relevant the delta is, and put the top items in front of a human in 90 seconds. A four-person credit desk covering 200 issuers cannot read every 10-Q the day it drops. This pipeline can — and it costs less than one analyst-hour per day to run the whole book. ## The Architecture ``` SequentialWorkflow ┌──────────────┐ │ EDGAR Feed │ (cron polls EDGAR every ~15 min for new filings) └──────┬───────┘ │ accession numbers ▼ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │ Filing Classifier │ → │ Section Extractor │ → │ Diff Engine │ │ (gpt-4.1-mini) │ │ (gpt-4.1) │ │ (claude-opus-4-8) │ │ 10-K / 10-Q / 8-K │ │ MD&A, Risk, Notes │ │ vs. prior period │ └─────────────────────┘ └─────────────────────┘ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ ┌─────────────────────┐ │ Memo Writer │ ← │ Materiality Scorer │ │ (claude-sonnet-4-5) │ │ (claude-sonnet-4-5) │ └──────────┬──────────┘ └─────────────────────┘ │ ▼ ┌──────────────┐ │ Research DB │ └──────────────┘ ``` ## Step 1: Setup ```bash theme={null} pip install requests python-dotenv ``` Create a `.env` file. SEC requires a descriptive `User-Agent` on every EDGAR request (see [SEC EDGAR access rules](https://www.sec.gov/os/accessing-edgar-data)) — set one that identifies your firm and a reachable email: ```bash theme={null} SWARMS_API_KEY=your_api_key_here EDGAR_USER_AGENT="Acme Capital Research research@acmecap.com" PRIOR_FILINGS_DB_URL=postgres://... # where you stash prior accession texts ``` Grab your Swarms key at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). ```python theme={null} import json import os from datetime import datetime, timedelta import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") EDGAR_UA = os.getenv("EDGAR_USER_AGENT") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Five OpenAI-format function tools. The agents decide when to call them; the swarm runtime carries arguments and return values between stages. ```python theme={null} FETCH_EDGAR_FILING = { "type": "function", "function": { "name": "fetch_edgar_filing", "description": ( "Fetch the full text of an SEC filing from EDGAR by accession " "number. Returns the raw filing text, the form type (10-K, 10-Q, " "8-K, etc.), the filer CIK, and the period of report." ), "parameters": { "type": "object", "properties": { "accession_number": { "type": "string", "description": ( "EDGAR accession number, e.g. 0000320193-24-000123. " "Dashes required." ), }, }, "required": ["accession_number"], }, }, } PARSE_MDA_SECTION = { "type": "function", "function": { "name": "parse_mda_section", "description": ( "Extract the Management's Discussion and Analysis (MD&A) section " "from the full text of a 10-K or 10-Q filing. Returns the MD&A " "as clean text with subsection headers preserved." ), "parameters": { "type": "object", "properties": { "filing_text": { "type": "string", "description": "Full raw text of the EDGAR filing.", }, }, "required": ["filing_text"], }, }, } EXTRACT_RISK_FACTORS = { "type": "function", "function": { "name": "extract_risk_factors", "description": ( "Extract Item 1A (Risk Factors) from a 10-K, or the updated risk " "factor language from a 10-Q. Returns each risk factor as an " "individually addressable string in an array." ), "parameters": { "type": "object", "properties": { "filing_text": { "type": "string", "description": "Full raw text of the EDGAR filing.", }, }, "required": ["filing_text"], }, }, } DIFF_SECTIONS = { "type": "function", "function": { "name": "diff_sections", "description": ( "Compare a section of the current filing against the same " "section of the prior comparable filing. Returns a semantic " "diff: added language, removed language, and language with " "changed meaning even if wording is similar." ), "parameters": { "type": "object", "properties": { "current_text": { "type": "string", "description": ( "Section text from the new filing (e.g. MD&A from " "the latest 10-Q)." ), }, "prior_text": { "type": "string", "description": ( "Same section from the prior comparable filing " "(prior 10-Q for a 10-Q, prior 10-K for a 10-K)." ), }, }, "required": ["current_text", "prior_text"], }, }, } SCORE_MATERIALITY = { "type": "function", "function": { "name": "score_materiality", "description": ( "Score the materiality of a diff on a 0-100 scale. 0 = pure " "boilerplate cleanup, 100 = thesis-breaking new disclosure. " "Returns the score, a one-line rationale, and a category " "(GUIDANCE, LITIGATION, ACCOUNTING, SEGMENT, LIQUIDITY, OTHER)." ), "parameters": { "type": "object", "properties": { "diff_text": { "type": "string", "description": ( "The semantic diff output from diff_sections." ), }, }, "required": ["diff_text"], }, }, } ``` ## Step 3: Define the Pipeline Agents Five agents in a `SequentialWorkflow`. Each stage builds on the prior stage's output. Models are deliberately diversified — a cheap classifier on the front, two Claude models doing the deep legal-language work in the middle, and Sonnet writing the final memo. ```python theme={null} PIPELINE_AGENTS = [ { "agent_name": "Filing Classifier", "description": "Identifies form type and routes the pipeline.", "system_prompt": ( "You are an SEC filing classifier. Given an accession number, " "call fetch_edgar_filing, then output a single JSON object: " '{"accession": str, "form_type": "10-K"|"10-Q"|"8-K", ' '"cik": str, "period_of_report": "YYYY-MM-DD", ' '"prior_accession": str | null}. The prior_accession is the ' "same filer's most recent comparable filing (prior 10-Q for a " "10-Q, prior 10-K for a 10-K, null for an 8-K). Output JSON " "only — no prose." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.0, "tools_list_dictionary": [FETCH_EDGAR_FILING], }, { "agent_name": "Section Extractor", "description": "Pulls MD&A, Risk Factors, and footnotes.", "system_prompt": ( "You are an SEC filing section extractor. Given the classifier " "output and the filing text, call parse_mda_section and " "extract_risk_factors. Also extract any financial-statement " "footnotes that discuss revenue recognition, going concern, " "subsequent events, or commitments and contingencies. Output " "a JSON object with keys: mda, risk_factors (array), footnotes " "(object keyed by footnote topic). Preserve all numbers and " "section headers verbatim — do not paraphrase." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.1, "tools_list_dictionary": [PARSE_MDA_SECTION, EXTRACT_RISK_FACTORS], }, { "agent_name": "Diff Engine", "description": "Semantic diff vs. the prior comparable filing.", "system_prompt": ( "You are a senior securities lawyer comparing two filings. For " "each extracted section (MD&A, each Risk Factor, each footnote), " "fetch the same section from prior_accession and call " "diff_sections. Surface: (1) NEW language not present in the " "prior period, (2) REMOVED language present prior but not now, " "(3) CHANGED MEANING where wording is similar but the legal " "or financial implication has shifted. Be precise about which " "section each diff comes from. If a section is unchanged, say " "so explicitly — do not invent diffs. For 8-Ks (no prior), " "treat the entire filing as net-new." ), "model_name": "claude-opus-4-8", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.2, "tools_list_dictionary": [FETCH_EDGAR_FILING, PARSE_MDA_SECTION, EXTRACT_RISK_FACTORS, DIFF_SECTIONS], }, { "agent_name": "Materiality Scorer", "description": "0-100 score per diff, with category and rationale.", "system_prompt": ( "You are a buy-side analyst scoring each diff for thesis " "materiality. For every diff produced by the Diff Engine, call " "score_materiality. Output a JSON array of objects sorted by " "score descending: " '[{"section": str, "change_type": "NEW"|"REMOVED"|"CHANGED", ' '"diff_excerpt": str, "score": 0-100, ' '"category": "GUIDANCE"|"LITIGATION"|"ACCOUNTING"|"SEGMENT"|' '"LIQUIDITY"|"OTHER", "rationale": str}]. Be ruthless — most ' "10-Q diffs are boilerplate cleanup and should score under 20." ), "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, "tools_list_dictionary": [SCORE_MATERIALITY], }, { "agent_name": "Memo Writer", "description": "Produces the final analyst-facing memo.", "system_prompt": ( "You are writing a one-page memo for a portfolio manager. " "Format exactly:\n\n" "TICKER / CIK: <ticker> / <cik>\n" "FILING: <form_type> filed <date> for period <period>\n" "HEADLINE: <one sentence — the single most material change>\n\n" "TOP DELTAS (sorted by materiality):\n" " 1. [<score>/100, <category>] <section>: <one-sentence delta>\n" " 2. [<score>/100, <category>] <section>: <one-sentence delta>\n" " 3. [<score>/100, <category>] <section>: <one-sentence delta>\n\n" "READ-THROUGH: <two sentences on what this means for the thesis>\n" "NEXT STEP: <one of: NO ACTION | ANALYST READ | PM REVIEW | " "RISK COMMITTEE>\n\n" "Only include deltas scoring 30 or higher. If nothing scores " "above 30, say NO MATERIAL CHANGES and recommend NO ACTION." ), "model_name": "claude-sonnet-4-5", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.3, }, ] ``` ## Step 4: Process One Filing End-to-End Single accession number in, materiality-scored memo out. This is the unit you batch in Step 5. ```python theme={null} def triage_filing(accession_number: str) -> dict: payload = { "name": f"SEC Filing Triage — {accession_number}", "description": ( "Sequential pipeline: classify, extract, diff against prior, " "score materiality, write memo." ), "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": ( f"Triage SEC filing accession {accession_number}. Pass the " "output of each stage to the next. The final output must be " "a one-page memo per the Memo Writer spec." ), "agents": PIPELINE_AGENTS, } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) response.raise_for_status() return response.json() result = triage_filing("0000320193-24-000123") # example Apple 10-Q for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:800]) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` <Note> Persist only the Memo Writer's output to the research DB. The four upstream stages are the audit trail — when the PM asks "why is this scored 78?", you can walk them back through the Diff Engine output that produced the score. </Note> ## Step 5: Wire Up the EDGAR Firehose with Batch A real portfolio sees 30-50 new filings per day across its names — earnings season pushes that to 80+. Polling EDGAR every 15 minutes and triggering one swarm per filing burns a request per filing against the Free tier's 350/hour and 1,200/day caps. Batch the day's queue instead — `/v1/swarm/batch/completions` accepts up to 50 swarms per request, so chunk anything larger. ```python theme={null} EDGAR_RECENT_FILINGS = "https://www.sec.gov/cgi-bin/browse-edgar" EDGAR_HEADERS = {"User-Agent": EDGAR_UA, "Accept": "application/json"} PORTFOLIO_CIKS = [ # Top of book — one CIK per name "0000320193", # AAPL "0000789019", # MSFT "0001018724", # AMZN "0001045810", # NVDA # ... ~40 more in a real book ] def poll_new_filings(since: datetime) -> list[str]: """Return EDGAR accession numbers filed by portfolio CIKs since `since`.""" new_accessions = [] for cik in PORTFOLIO_CIKS: params = { "action": "getcompany", "CIK": cik, "type": "", # all form types "dateb": "", "owner": "include", "count": "10", "output": "atom", } r = requests.get( EDGAR_RECENT_FILINGS, params=params, headers=EDGAR_HEADERS, timeout=30, ) # Parse the atom feed for accession numbers filed after `since`. # (Your EDGAR parser of choice — sec-edgar-downloader, feedparser, etc.) new_accessions.extend(parse_atom_for_new(r.text, since)) # noqa return new_accessions # /v1/swarm/batch/completions accepts at most 50 swarms per request. BATCH_SIZE_LIMIT = 50 def triage_filings_batch(accession_numbers: list[str]) -> list[dict]: batch_payload = [] for acc in accession_numbers: batch_payload.append({ "name": f"SEC Filing Triage — {acc}", "description": "Sequential triage pipeline.", "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": ( f"Triage SEC filing accession {acc}. Pass the output of each " "stage to the next. Final output: one-page memo per spec." ), "agents": PIPELINE_AGENTS, }) results = [] for i in range(0, len(batch_payload), BATCH_SIZE_LIMIT): response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=batch_payload[i:i + BATCH_SIZE_LIMIT], timeout=1800, ) response.raise_for_status() results.extend(response.json()) return results # Run at 06:30 ET — picks up yesterday's late filings + this morning's 8-Ks since = datetime.utcnow() - timedelta(hours=18) new_filings = poll_new_filings(since) print(f"Triaging {len(new_filings)} new filings") results = triage_filings_batch(new_filings) with open(f"triage_{datetime.utcnow():%Y%m%d}.jsonl", "w") as f: for acc, result in zip(new_filings, results): # Batch items are shaped {"status", "swarm_name", "result", "usage"} — # the swarm's conversation lives under "result", not "output". memo = next( (o["content"] for o in result.get("result", []) if "Memo Writer" in o.get("role", "")), "", ) if isinstance(memo, list): memo = " ".join(str(c) for c in memo) f.write(json.dumps({ "accession": acc, "memo": memo, "cost": result["usage"]["billing_info"]["total_cost"], }) + "\n") total = sum(r["usage"]["billing_info"]["total_cost"] for r in results) print(f"Triaged {len(results)} filings for ${total:.2f}") ``` <Warning> `/v1/swarm/batch/completions` is a premium endpoint. A live EDGAR firehose at 30-50 filings/day per book will land you in Premium tier territory regardless — that is exactly the volume tier the batch endpoint was sized for. See [Premium Endpoints](/docs/documentation/resources/premium-endpoints). </Warning> ## Real Cost vs. Analyst Reading Time A buy-side analyst at a fully loaded \$300K/year costs roughly \$150/hour. A careful read of a 10-Q with a memo write-up is 15-20 minutes — call it \$45 of analyst time per filing, and that is the analyst who already covers the name. For 8-Ks across the book that the dedicated analyst does not read, the alternative is "nothing gets read" — which is the actual failure mode this pipeline addresses. | Scenario | Pipeline cost | Analyst-time cost | | -------------------------------------- | ------------- | ----------------- | | One filing (10-Q, \~5 sections diffed) | \~\$0.30 | \~\$45 | | Daily run (40 filings across the book) | \~\$12 | \~\$1,800 | | Annualized (250 trading days) | \~\$3,000 | \~\$450,000 | The pipeline is not replacing the analyst's read on the names they already cover. It is making sure the other 180 issuers in the credit book get a structured first-pass screen the same morning the filing drops — which is the only way a four-person desk covers a 200-name book without missing the 8-K that matters. ## Next Steps * Pair this with the [M\&A Due Diligence Swarm](/docs/examples/examples/ma-due-diligence) when a triage memo flags a strategic-review or transaction disclosure * Feed high-materiality memos into the [Sell-Side Research Pipeline](/docs/examples/examples/sell-side-research-pipeline) for full-length write-ups * Read the [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) for tuning model selection per stage once the pipeline is in production # Sell-Side Research Note → Trading Signal Pipeline Source: https://docs.swarms.ai/docs/examples/examples/sell-side-research-pipeline A HierarchicalSwarm that ingests sell-side PDFs from Goldman, JPM, MS, and BAML — extracts rating + target + thesis deltas in parallel — and emits a structured signal ranked against consensus before the open. ## What This Example Shows * A `HierarchicalSwarm` with a Research Director coordinating three specialist workers — Rating Tracker, Price Target Tracker, and Key Driver Extractor — running in parallel against a single PDF note * OpenAI-format function tools for PDF parsing, ratings/target regex extraction, consensus lookup, and Slack delivery * A mixed-provider agent team: Claude Sonnet 4.5 directing, GPT-4.1 / GPT-4.1-mini for surgical extraction, Gemini 2.5 Pro for long-document grounding * A consensus-check step that flags every new target as above, in line with, or below the street * End-of-day batch processing across 150+ notes via `/v1/swarm/batch/completions`, scheduled at 4:30pm ET, output is a ranked delta sheet * The structured signal payload your OMS, EMS, or research database actually wants — not free-form text <Info> This pipeline processes a high volume of PDF documents per day. The batch endpoint and parallel function-tool execution sit on the paid tiers (Pro, Ultra, Premium) — the Free tier caps you at 1,200 requests per day. Read the [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) before turning the cron on, and upgrade at [https://swarms.world/platform/account](https://swarms.world/platform/account). </Info> ## Why This Matters Every PM in the firm wakes up to a ranked sheet of rating + target deltas — already cross-referenced against consensus — for the price of one Bloomberg lunch. A multi-strategy PM gets roughly 150 sell-side notes hitting their inbox between 5am and 9am ET on any given trading day. Reading every page is physically impossible and almost entirely a waste — 95% of any sell-side note is restated boilerplate and an unchanged thesis. The actionable content is in the deltas: a Goldman analyst going from Buy to Hold, JPM lifting their target by 18%, Morgan Stanley swapping in a new bear case on China data center demand. Those three things move books. This pipeline does nothing except find those deltas, score them against street consensus, and put a structured signal in front of the PM before the bell. ## The Architecture ``` Email inbox / S3 drop | v +---------------+ | PDF Parser | (parse_pdf_note tool) +---------------+ | v +-------------------------------------------------+ | HierarchicalSwarm | | | | +-----------------------------+ | | | Research Director | | | | (claude-sonnet-4.5) | | | +-------------+---------------+ | | | | | +-------------+-------------+ | | | | | | | v v v | | +-----------+ +-----------+ +-----------+ | | | Rating | | Price | | Key | | | | Tracker | | Target | | Driver | | | | gpt-4.1 | | Tracker | | Extractor | | | | -mini | | gpt-4.1 | | gemini | | | +-----------+ +-----------+ +-----------+ | +-------------------------------------------------+ | v +-----------------+ | Consensus Check | (lookup_consensus_target) +-----------------+ | v +-----------------+ | Signal Payload | (structured JSON) +-----------------+ | +--------+--------+ | | v v +----------+ +----------+ | DB | | Slack | +----------+ +----------+ ``` ## Step 1: Setup Install dependencies and configure credentials. The pipeline needs your Swarms API key plus either IMAP credentials for an inbox sweep or an S3 bucket where your prime broker drops PDFs. ```bash theme={null} pip install requests python-dotenv export SWARMS_API_KEY="your-api-key-here" export RESEARCH_INBOX_HOST="imap.your-firm.com" export RESEARCH_INBOX_USER="research-inbox@your-firm.com" export RESEARCH_INBOX_PASS="..." export RESEARCH_S3_BUCKET="firm-sell-side-notes" export RESEARCH_S3_PREFIX="2026/incoming/" export CONSENSUS_API_URL="https://your-internal-consensus-service/v1" export SLACK_RESEARCH_WEBHOOK="https://hooks.slack.com/services/..." ``` ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Function Tools Every worker agent gets the tools it actually needs — nothing more. Tools are OpenAI-format function schemas; your runtime resolves the calls server-side or replays them locally after the swarm finishes, depending on your tool host. ```python theme={null} PARSE_PDF_TOOL = { "type": "function", "function": { "name": "parse_pdf_note", "description": ( "Download a sell-side research PDF (URL or base64) and return its " "extracted plaintext, page count, and detected broker." ), "parameters": { "type": "object", "properties": { "pdf_url_or_b64": { "type": "string", "description": "HTTPS URL to the PDF or a base64-encoded PDF payload.", }, }, "required": ["pdf_url_or_b64"], }, }, } EXTRACT_RATING_TOOL = { "type": "function", "function": { "name": "extract_rating", "description": ( "Parse the broker rating (Buy / Overweight / Hold / Neutral / Sell / " "Underweight) and any change vs. the prior published rating." ), "parameters": { "type": "object", "properties": { "text": {"type": "string", "description": "Full note plaintext."}, }, "required": ["text"], }, }, } EXTRACT_TARGET_TOOL = { "type": "function", "function": { "name": "extract_price_target", "description": ( "Pull the new 12-month price target and the prior target from the note. " "Return both numerics plus the percent change." ), "parameters": { "type": "object", "properties": { "text": {"type": "string", "description": "Full note plaintext."}, }, "required": ["text"], }, }, } EXTRACT_DRIVERS_TOOL = { "type": "function", "function": { "name": "extract_thesis_drivers", "description": ( "Identify the 3-5 key thesis drivers the analyst leans on in this note. " "Each driver should be a short noun phrase grounded in a quoted line." ), "parameters": { "type": "object", "properties": { "text": {"type": "string", "description": "Full note plaintext."}, }, "required": ["text"], }, }, } LOOKUP_CONSENSUS_TOOL = { "type": "function", "function": { "name": "lookup_consensus_target", "description": ( "Fetch the current street-mean 12-month price target for a ticker from " "the firm's internal consensus service." ), "parameters": { "type": "object", "properties": { "ticker": {"type": "string", "description": "Equity ticker, e.g. NVDA."}, }, "required": ["ticker"], }, }, } IS_ABOVE_CONSENSUS_TOOL = { "type": "function", "function": { "name": "is_above_consensus", "description": ( "Compare a new broker target against street consensus and return a " "categorical flag: 'above' / 'in_line' / 'below' plus the percent gap." ), "parameters": { "type": "object", "properties": { "target": {"type": "number", "description": "Broker's new 12-month target."}, "ticker": {"type": "string", "description": "Equity ticker."}, }, "required": ["target", "ticker"], }, }, } POST_SIGNAL_TOOL = { "type": "function", "function": { "name": "post_signal_to_slack", "description": ( "Publish a structured signal payload to the #research-signals Slack " "channel. Used only after the Research Director has validated the JSON." ), "parameters": { "type": "object", "properties": { "payload": { "type": "object", "description": "The signal JSON object — see Step 6 for schema.", }, }, "required": ["payload"], }, }, } ``` ## Step 3: Define the Four Agents The Research Director is the only agent with the `coordinator` role — it owns synthesis, consensus reasoning, and the final signal payload. The three workers each get exactly the tools their job requires. ```python theme={null} RESEARCH_DIRECTOR_PROMPT = ( "You are the Director of Research at a multi-strategy hedge fund. " "Your three specialists hand you (1) the broker's new rating + any change, " "(2) the new and prior price targets with percent move, and (3) the key " "thesis drivers. Your job: synthesize these into a single signal payload. " "Always call lookup_consensus_target and is_above_consensus on the new target. " "Reject the signal if no rating, target, or drivers can be extracted with " "confidence — better to skip than to publish noise. Output the final signal " "as strict JSON matching the schema in your system context." ) RATING_TRACKER_PROMPT = ( "You track sell-side rating changes. Given the plaintext of one research note, " "call extract_rating exactly once. Return: broker, ticker, prior_rating, " "new_rating, and a 'changed' boolean. If the note is a reiteration with no " "rating change, say so explicitly — do not fabricate a change." ) PRICE_TARGET_PROMPT = ( "You track sell-side price target changes. Given the plaintext of one research " "note, call extract_price_target exactly once. Return: prior_target, new_target, " "currency, and percent_change. If only a new target is published with no prior, " "mark prior_target as null — do not guess." ) KEY_DRIVER_PROMPT = ( "You extract the substantive thesis drivers from a sell-side note. Call " "extract_thesis_drivers exactly once. Return 3-5 drivers, each as a short noun " "phrase with a one-sentence quote that grounds it in the note. Ignore " "boilerplate, disclosure text, and prior-period restatements." ) def build_swarm_for_note(pdf_ref: str, ticker: str) -> dict: return { "name": f"Sell-Side Note Signal — {ticker}", "description": "Research Director coordinating Rating, Target, and Driver workers.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( f"A sell-side research note on {ticker} just landed at {pdf_ref}. " f"Call parse_pdf_note first, then dispatch the three workers in parallel. " f"Synthesize their output into the structured signal payload. Cross-check " f"the new target against street consensus before emitting the signal." ), "agents": [ { "agent_name": "Research Director", "description": "Director — synthesizes worker output into a signal.", "system_prompt": RESEARCH_DIRECTOR_PROMPT, "model_name": "anthropic/claude-sonnet-4-5", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, "temperature": 0.1, "tools_list_dictionary": [ PARSE_PDF_TOOL, LOOKUP_CONSENSUS_TOOL, IS_ABOVE_CONSENSUS_TOOL, POST_SIGNAL_TOOL, ], }, { "agent_name": "Rating Tracker", "description": "Extracts rating + rating change.", "system_prompt": RATING_TRACKER_PROMPT, "model_name": "openai/gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.0, "tools_list_dictionary": [EXTRACT_RATING_TOOL], }, { "agent_name": "Price Target Tracker", "description": "Extracts new vs. prior price target.", "system_prompt": PRICE_TARGET_PROMPT, "model_name": "openai/gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.0, "tools_list_dictionary": [EXTRACT_TARGET_TOOL], }, { "agent_name": "Key Driver Extractor", "description": "Pulls the 3-5 thesis drivers from the note body.", "system_prompt": KEY_DRIVER_PROMPT, "model_name": "gemini/gemini-2.5-pro", "role": "worker", "max_loops": 1, "max_tokens": 2048, "temperature": 0.2, "tools_list_dictionary": [EXTRACT_DRIVERS_TOOL], }, ], } ``` <Note> The model mix is deliberate. Rating extraction is a small classification problem — `gpt-4.1-mini` is plenty and roughly 5x cheaper. Target extraction needs careful number handling — `gpt-4.1` earns its keep. Driver extraction is the only step that reads the full multi-page document end to end, and Gemini 2.5 Pro is empirically the strongest on long-document grounding. The Director uses Claude Sonnet 4.5 because synthesis + tool-call orchestration is what it was built for. </Note> ## Step 4: Process One Note End-to-End Start with a single note. This is the loop you scale. ```python theme={null} def run_single_note(pdf_ref: str, ticker: str) -> dict: payload = build_swarm_for_note(pdf_ref, ticker) response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) response.raise_for_status() return response.json() result = run_single_note( pdf_ref="s3://firm-sell-side-notes/2026/incoming/gs_nvda_2026_05_28.pdf", ticker="NVDA", ) for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:600]) print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` The Research Director's last message is the signal payload you persist. The three worker outputs are the audit trail — every signal is fully reproducible from the source PDF plus the worker briefs. ## Step 5: End-of-Day Batch Across All Notes The real value shows up when you sweep the entire inbox in one shot. Build a payload list keyed by the day's PDF drops and hand the whole thing to `/v1/swarm/batch/completions`. ```python theme={null} def sweep_inbox_for_today() -> list[tuple[str, str]]: """Return [(pdf_ref, ticker), ...] for every note that arrived today.""" # Replace with your IMAP/S3 implementation. Each entry is a tuple of # (s3_uri_or_url, primary_ticker_detected_from_subject_or_filename). return [ ("s3://firm-sell-side-notes/2026/incoming/gs_nvda_2026_05_28.pdf", "NVDA"), ("s3://firm-sell-side-notes/2026/incoming/jpm_amd_2026_05_28.pdf", "AMD"), ("s3://firm-sell-side-notes/2026/incoming/ms_avgo_2026_05_28.pdf", "AVGO"), # ... ~150 of these per day on a real desk ] def run_eod_batch() -> list[dict]: notes = sweep_inbox_for_today() payload = [build_swarm_for_note(pdf_ref, ticker) for pdf_ref, ticker in notes] response = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=headers, json=payload, timeout=1800, ) response.raise_for_status() return response.json() results = run_eod_batch() signals: list[dict] = [] for r in results: director_msg = next( (o for o in r.get("result", []) if "Research Director" in o.get("role", "")), None, ) if not director_msg: continue content = director_msg["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) try: signals.append(json.loads(str(content))) except json.JSONDecodeError: continue # Rank by conviction, then by absolute target move vs. consensus signals.sort( key=lambda s: ( {"HIGH": 3, "MEDIUM": 2, "LOW": 1}.get(s.get("conviction", "LOW"), 0), abs(s.get("vs_consensus", {}).get("pct_gap", 0)), ), reverse=True, ) with open("eod_signals.jsonl", "w") as f: for sig in signals: f.write(json.dumps(sig) + "\n") total_cost = sum( r.get("usage", {}).get("billing_info", {}).get("total_cost", 0) for r in results ) print(f"Processed {len(results)} notes — emitted {len(signals)} signals for ${total_cost:.2f}") ``` <Info> Schedule this script as a cron job for 4:30pm ET on weekdays. The post-close window means every note that hit the inbox during regular trading hours is captured, the consensus service has finished its end-of-day refresh, and the PM sees the ranked delta sheet on Slack before they leave the desk — not in their pre-market inbox the next morning. </Info> ## Step 6: The Output Schema The Research Director is constrained to emit signals in this exact shape. This is the contract your OMS, EMS, research database, and PM Slack channel all consume. ```json theme={null} { "ticker": "NVDA", "broker": "Goldman Sachs", "analyst": "Toshiya Hari", "note_id": "gs_nvda_2026_05_28", "published_at": "2026-05-28T06:42:00Z", "prior_rating": "Buy", "new_rating": "Buy", "rating_changed": false, "prior_target": 165.0, "new_target": 195.0, "target_pct_change": 18.18, "currency": "USD", "vs_consensus": { "consensus_target": 178.45, "flag": "above", "pct_gap": 9.28 }, "drivers": [ { "label": "Blackwell ramp ahead of plan", "quote": "Channel checks indicate Blackwell production is tracking 12-15% above the prior Street model into Q3." }, { "label": "Sovereign AI pipeline conversion", "quote": "Three new sovereign customers in EMEA moved from MoU to firm orders this quarter." }, { "label": "Networking attach rate expansion", "quote": "Spectrum-X attach rates inside HGX clusters now exceed 70% versus our prior 55% assumption." } ], "conviction": "HIGH", "audit_trail": { "rating_tracker_output": "...", "price_target_tracker_output": "...", "key_driver_extractor_output": "..." } } ``` The `audit_trail` block is what makes this defensible in a compliance review — every field in the signal traces back to a specific worker output, which traces back to a specific line in the PDF. ## Real Cost vs. Junior Analyst Reading Notes | Scenario | Per note | Per trading day (150 notes) | Annualized (\~250 days) | | ---------------------------------------------------- | -------- | --------------------------- | ----------------------------------- | | HierarchicalSwarm pipeline (mixed-provider, batched) | \~\$0.25 | \~\$38 | \~\$9,500 | | Junior analyst (fully loaded \$150k) reading notes | — | Maxes out at \~20 notes/day | \$150,000 — and they skip dinner | | Two-analyst rotation just for note triage | — | \~40 notes/day | \$300,000 — and they still miss 110 | The swarm is not reading notes for fun — it is producing a structured, ranked signal sheet that ties every delta back to the underlying quote. Your humans stop being PDF janitors and start spending their time on the names where the signal is actually interesting. ## Next Steps * [Build an AI Hedge Fund Research Pipeline](/docs/examples/examples/ai-hedge-fund) — the upstream watchlist research note that the signal sheet feeds into * [SEC Filing Triage Pipeline](/docs/examples/examples/sec-filing-triage-pipeline) — same pattern applied to 10-K/10-Q/8-K dumps from EDGAR * [Earnings Call Analysis Swarm](/docs/examples/examples/earnings-call-analysis-swarm) — extend the pipeline to live transcript ingestion during earnings season # SEO Content Generation Pipeline Source: https://docs.swarms.ai/docs/examples/examples/seo-content-pipeline Build a production-grade SEO content factory using a 4-agent Graph Workflow — feed it a URL or company description and get a fully optimized article ready to publish This tutorial walks you through building a complete **SEO content generation application** powered by a 4-agent graph workflow. Give it a competitor URL, your own website, or a plain-text company description — the pipeline fetches the content, researches keywords, writes a long-form SEO article, and delivers a publish-ready, fully-optimized piece. <Warning> **Premium Tier Required**: Graph Workflow is available on Pro, Ultra, and Premium plans. [Upgrade your account](https://swarms.world/platform/account) to access this endpoint. </Warning> *** ## What You Will Build A fully automated content engine that: * Accepts a **URL** (website, blog post, product page) *or* a **plain-text company description** * Fetches and extracts readable text from any URL using `BeautifulSoup` * Runs a **4-agent Graph Workflow** where two specialist agents work in parallel, then converge into a writer and a final SEO optimizer * Returns a publish-ready article complete with meta title, meta description, heading hierarchy, keyword density notes, schema markup recommendations, and internal-linking suggestions *** ## Architecture ### Agent Roles | Agent | Role | Stage | | --------------------- | -------------------------------------------------------------------------------------------------- | ------------------- | | **ContentAnalyst** | Extracts brand voice, offerings, value props, and target audience from the source content | Entry (parallel) | | **KeywordStrategist** | Identifies primary keywords, long-tail variations, search intent, and topic clusters | Entry (parallel) | | **SEOWriter** | Synthesizes both analyses into a 1,500-word SEO article with optimized structure | Middle (sequential) | | **SEOPublisher** | Adds meta tags, schema markup, heading-tag audit, internal-link suggestions, and readability score | End (sequential) | ### Graph Flow ``` [ContentAnalyst] ──┐ ├──> [SEOWriter] ──> [SEOPublisher] [KeywordStrategist]──┘ ``` Both `ContentAnalyst` and `KeywordStrategist` run **in parallel** the moment the workflow starts. Once both finish, `SEOWriter` receives all their outputs and drafts the article. Finally `SEOPublisher` performs a full SEO polish and delivers the ready-to-publish result. ```mermaid theme={null} graph LR A["ContentAnalyst (Entry)"] --> C[SEOWriter] B["KeywordStrategist (Entry)"] --> C C --> D["SEOPublisher (End)"] style A fill:#1e40af,color:#fff style B fill:#1e40af,color:#fff style C fill:#7c3aed,color:#fff style D fill:#065f46,color:#fff ``` *** ## Prerequisites ### 1. Get Your API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Ensure you have a **Pro or Ultra plan** 4. Generate a new API key and export it: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### 2. Install Dependencies ```bash theme={null} pip install requests beautifulsoup4 lxml ``` *** ## Full Application Code ### `seo_pipeline.py` ```python theme={null} """ SEO Content Generation Pipeline ================================ Uses a 4-agent Graph Workflow to generate publish-ready SEO articles from a URL or a plain-text company description. Usage: python seo_pipeline.py --url https://example.com python seo_pipeline.py --description "We build AI-powered CRM software..." python seo_pipeline.py --url https://example.com --keyword "ai crm software" """ import os import sys import argparse import requests from bs4 import BeautifulSoup # ── Configuration ────────────────────────────────────────────────────────────── API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") MODEL = "gpt-5.4" HEADERS = { "x-api-key": API_KEY, "Content-Type": "application/json", } # ── Step 1: Content Fetching ─────────────────────────────────────────────────── def fetch_url_content(url: str, max_chars: int = 8000) -> str: """ Fetch a URL and return clean readable text extracted from the page body. Strips navigation, scripts, and boilerplate; keeps paragraphs, headings, and list items to preserve meaningful context for the AI agents. """ try: response = requests.get(url, timeout=20, headers={ "User-Agent": ( "Mozilla/5.0 (compatible; SEO-Pipeline/1.0; " "+https://swarms.world)" ) }) response.raise_for_status() except requests.RequestException as exc: raise SystemExit(f"[ERROR] Could not fetch '{url}': {exc}") from exc soup = BeautifulSoup(response.text, "lxml") for tag in soup(["script", "style", "nav", "footer", "header", "aside", "form", "noscript", "iframe"]): tag.decompose() text_parts = [] for element in soup.find_all( ["h1", "h2", "h3", "h4", "p", "li", "td", "blockquote", "article"] ): text = element.get_text(separator=" ", strip=True) if len(text) > 30: text_parts.append(text) raw_text = "\n\n".join(text_parts) if len(raw_text) > max_chars: raw_text = raw_text[:max_chars] + "\n\n[...content truncated for length...]" return raw_text def get_source_content(url, description): """ Returns (source_text, source_label) from either a URL or a description. """ if url: print(f"[INFO] Fetching content from: {url}") text = fetch_url_content(url) label = f"Website URL: {url}" print(f"[INFO] Extracted {len(text):,} characters from the page.") return text, label if description: return description.strip(), "Company description provided by user" raise ValueError("Provide either --url or --description.") # ── Step 2: Graph Workflow Definition ───────────────────────────────────────── def build_workflow(source_content: str, source_label: str, focus_keyword: str = "") -> dict: """ Build the 4-agent SEO Graph Workflow payload. Graph structure: [ContentAnalyst] ──┐ ├──> [SEOWriter] ──> [SEOPublisher] [KeywordStrategist]──┘ """ keyword_hint = ( f"\nThe primary keyword to target is: **{focus_keyword}**" if focus_keyword else "" ) task = ( f"Generate a complete, publish-ready SEO article based on the " f"following source material.\n\n" f"Source: {source_label}{keyword_hint}\n\n" f"--- SOURCE CONTENT ---\n{source_content}\n--- END OF SOURCE ---" ) return { "name": "SEO-Content-Generation-Pipeline", "description": ( "4-agent graph workflow: parallel content analysis + keyword " "research → SEO article writing → full SEO optimization" ), "task": task, "agents": [ { "agent_name": "ContentAnalyst", "description": "Extracts brand identity and content strategy signals", "system_prompt": ( "You are a senior content strategist and brand analyst. " "Analyze the provided source material and extract:\n\n" "1. **Company / Brand Overview** — What does the company do?\n" "2. **Core Products & Services** — List and briefly describe each.\n" "3. **Target Audience** — Industry, role, pain points.\n" "4. **Unique Value Propositions** — What differentiates this brand?\n" "5. **Brand Voice & Tone** — Formal, conversational, technical?\n" "6. **Key Topics & Themes** — Recurring subjects in the content.\n" "7. **Content Gaps** — Important unanswered questions.\n\n" "Be thorough. Your analysis feeds directly into an SEO article writer." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 4000, }, { "agent_name": "KeywordStrategist", "description": "Builds a data-informed keyword and topic strategy", "system_prompt": ( "You are an expert SEO keyword strategist. Analyze the source material " "and produce a comprehensive keyword strategy including:\n\n" "1. **Primary Keyword** — The single most relevant, high-intent phrase.\n" "2. **Secondary Keywords** — 5-8 supporting keyword phrases.\n" "3. **Long-Tail Keywords** — 8-12 specific, lower-competition phrases.\n" "4. **LSI / Semantic Keywords** — 10-15 related terms.\n" "5. **Search Intent Mapping** — Informational, Navigational, Commercial, or Transactional.\n" "6. **Topic Clusters** — 3-5 content pillars.\n" "7. **Competitor Content Gaps** — Angles competitors miss.\n" "8. **Featured Snippet Opportunities** — 3-5 question-format headings.\n\n" "Your keyword strategy will be used to write the article." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 4000, }, { "agent_name": "SEOWriter", "description": "Writes a full-length, keyword-optimized SEO article", "system_prompt": ( "You are a world-class SEO content writer. You will receive:\n" "- A brand/content analysis from a Content Analyst\n" "- A keyword strategy from a Keyword Strategist\n\n" "Write a comprehensive SEO article following these requirements:\n\n" "**Structure Requirements:**\n" "- Length: 1,400-1,800 words\n" "- H1 title (include primary keyword naturally)\n" "- Compelling intro paragraph (hook + problem statement)\n" "- 4-6 H2 sections, each with 2-3 supporting paragraphs\n" "- At least 2 H3 subsections within any complex H2 section\n" "- Use numbered lists or bullet points where appropriate\n" "- A strong conclusion with a clear call-to-action (CTA)\n\n" "**SEO Writing Requirements:**\n" "- Place the primary keyword in: title, first paragraph, at least one H2, and the conclusion\n" "- Weave secondary keywords naturally throughout\n" "- Write in active voice; keep sentences under 25 words where possible\n" "- Output the complete article in Markdown format." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.55, "max_tokens": 6000, }, { "agent_name": "SEOPublisher", "description": "Applies final SEO optimizations and generates publish metadata", "system_prompt": ( "You are an SEO technical editor. Take the completed article and produce " "a complete publish package with these sections:\n\n" "1. PUBLISH METADATA\n" " - Meta Title (50-60 chars, includes primary keyword)\n" " - Meta Description (145-160 chars, includes primary + secondary keyword)\n" " - URL Slug (lowercase, hyphenated, keyword-rich)\n" " - Primary Keyword, Secondary Keywords, Estimated Read Time, Word Count\n\n" "2. SCHEMA MARKUP\n" " Provide ready-to-use JSON-LD schema (Article, HowTo, or FAQPage).\n\n" "3. HEADING AUDIT\n" " List all headings with a pass or flag. Suggest improvements.\n\n" "4. INTERNAL LINKING SUGGESTIONS\n" " Suggest 5-7 anchor text phrases with the type of page to link to.\n\n" "5. READABILITY REPORT\n" " - Estimated Flesch Reading Ease score\n" " - Passive voice instances to fix\n\n" "6. OPTIMIZED ARTICLE\n" " The final, fully-optimized version of the article in Markdown." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 8000, }, ], "edges": [ {"source": "ContentAnalyst", "target": "SEOWriter"}, {"source": "KeywordStrategist", "target": "SEOWriter"}, {"source": "SEOWriter", "target": "SEOPublisher"}, ], "entry_points": ["ContentAnalyst", "KeywordStrategist"], "end_points": ["SEOPublisher"], "max_loops": 1, } # ── Step 3: Run the Workflow ─────────────────────────────────────────────────── def run_seo_pipeline(workflow_config: dict) -> dict: print("[INFO] Submitting workflow to Swarms API...") response = requests.post( f"{API_BASE_URL}/v1/graph-workflow/completions", headers=HEADERS, json=workflow_config, timeout=300, ) if response.status_code != 200: raise SystemExit( f"[ERROR] API returned {response.status_code}: {response.text}" ) return response.json() # ── Step 4: Display Results ──────────────────────────────────────────────────── PIPELINE_STAGES = [ ("STAGE 1 — PARALLEL ANALYSIS", ["ContentAnalyst", "KeywordStrategist"]), ("STAGE 2 — SEO ARTICLE DRAFT", ["SEOWriter"]), ("STAGE 3 — PUBLISH PACKAGE", ["SEOPublisher"]), ] def display_results(result: dict) -> None: print(f"\n{'='*70}") print(f" WORKFLOW: {result.get('name', 'SEO Pipeline')}") print(f" STATUS: {result.get('status', 'unknown').upper()}") print(f"{'='*70}") outputs = result.get("outputs", {}) for stage_label, agent_names in PIPELINE_STAGES: print(f"\n{'─'*70}") print(f" {stage_label}") print(f"{'─'*70}") for agent_name in agent_names: if agent_name not in outputs: print(f"\n [{agent_name}] — no output received") continue output = outputs[agent_name] if isinstance(output, list): output = "\n".join(str(item) for item in output) print(f"\n [{agent_name}]") lines = str(output).splitlines() for line in lines[:120]: print(f" {line}") if len(lines) > 120: print(f"\n ... [{len(lines) - 120} more lines] ...") usage = result.get("usage", {}) total_cost = usage.get("token_cost", "N/A") total_tokens = usage.get("total_tokens", "N/A") print(f"\n{'='*70}") print(f" Total Tokens : {total_tokens}") print(f" Total Cost : ${total_cost}") print(f"{'='*70}\n") # ── Step 5: Save Output ──────────────────────────────────────────────────────── def save_article(result: dict, output_file: str = "seo_article.md") -> None: outputs = result.get("outputs", {}) publisher_output = outputs.get("SEOPublisher", "") if isinstance(publisher_output, list): publisher_output = "\n".join(str(i) for i in publisher_output) if not publisher_output: print("[WARN] SEOPublisher produced no output — nothing saved.") return with open(output_file, "w", encoding="utf-8") as fh: fh.write(publisher_output) print(f"[INFO] Full publish package saved to: {output_file}") # ── CLI Entry Point ──────────────────────────────────────────────────────────── def parse_args(): parser = argparse.ArgumentParser( description="Generate SEO content from a URL or company description." ) group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--url", metavar="URL") group.add_argument("--description", metavar="TEXT") parser.add_argument("--keyword", metavar="KEYWORD", default="") parser.add_argument("--output", metavar="FILE", default="seo_article.md") return parser.parse_args() def main() -> None: args = parse_args() source_text, source_label = get_source_content(args.url, args.description) workflow = build_workflow(source_text, source_label, args.keyword) result = run_seo_pipeline(workflow) display_results(result) save_article(result, args.output) if __name__ == "__main__": main() ``` *** ## Running the Application ### Option A — Analyze a Website URL ```bash theme={null} python seo_pipeline.py --url https://yourcompany.com ``` ### Option B — Analyze a Specific Page ```bash theme={null} python seo_pipeline.py \ --url https://yourcompany.com/product/ai-crm \ --keyword "ai crm software for startups" ``` ### Option C — Use a Company Description ```bash theme={null} python seo_pipeline.py \ --description "Acme Corp builds AI-powered CRM software for B2B SaaS companies. Our product automates lead scoring, meeting scheduling, and follow-up emails." \ --keyword "ai crm for small business" ``` ### Option D — Save to a Custom File ```bash theme={null} python seo_pipeline.py \ --url https://yourcompany.com \ --output articles/homepage-seo.md ``` *** ## How the Graph Executes ``` Timeline (approximate): t=0s ├── ContentAnalyst starts ──────────────────┐ │ │ (parallel) t=0s └── KeywordStrategist starts ─────────────────┤ │ t=15s Both complete ─────────────────────────────────┤ │ t=15s SEOWriter receives both outputs, starts ───────┤ │ t=40s SEOWriter completes ───────────────────────────┤ │ t=40s SEOPublisher receives article, starts ─────────┤ │ t=60s SEOPublisher completes ────────────────────────┘ Total: ~60-90 seconds for a complete publish package ``` *** ## Using the API Directly (No URL Fetching) <Tabs> <Tab title="Python (requests)"> ```python theme={null} import os import requests API_KEY = os.environ.get("SWARMS_API_KEY") MODEL = "gpt-5.4" workflow = { "name": "SEO-Content-Generation-Pipeline", "description": "4-agent SEO content factory", "task": ( "Generate a publish-ready SEO article for: Acme Corp — AI-powered CRM for B2B SaaS startups.\n" "Products: LeadScore AI, MeetBot, FollowUp Engine.\n" "Primary keyword to target: 'ai crm for small business'" ), "agents": [ { "agent_name": "ContentAnalyst", "system_prompt": ( "You are a senior content strategist. Analyze the source material " "and extract: company overview, products/services, target audience, " "unique value propositions, brand voice, key themes, and content gaps." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 4000, }, { "agent_name": "KeywordStrategist", "system_prompt": ( "You are an SEO keyword strategist. Produce: primary keyword, " "5-8 secondary keywords, 8-12 long-tail phrases, LSI terms, " "search intent mapping, topic clusters, and featured snippet opportunities." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 4000, }, { "agent_name": "SEOWriter", "system_prompt": ( "You are an SEO content writer. Using the brand analysis and keyword " "strategy from previous agents, write a 1,400-1,800 word SEO article " "in Markdown with H1, H2/H3 structure, bullet lists, and a CTA conclusion." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.55, "max_tokens": 6000, }, { "agent_name": "SEOPublisher", "system_prompt": ( "You are an SEO technical editor. Produce a full publish package: " "meta title/description/slug, JSON-LD schema, heading audit, " "internal linking suggestions, readability report, and final optimized article." ), "model_name": MODEL, "max_loops": 1, "temperature": 0.3, "max_tokens": 8000, }, ], "edges": [ {"source": "ContentAnalyst", "target": "SEOWriter"}, {"source": "KeywordStrategist", "target": "SEOWriter"}, {"source": "SEOWriter", "target": "SEOPublisher"}, ], "entry_points": ["ContentAnalyst", "KeywordStrategist"], "end_points": ["SEOPublisher"], "max_loops": 1, } response = requests.post( "https://api.swarms.world/v1/graph-workflow/completions", headers={"x-api-key": API_KEY, "Content-Type": "application/json"}, json=workflow, timeout=300, ) result = response.json() print(result["outputs"]["SEOPublisher"]) ``` </Tab> <Tab title="Shell (curl)"> ```bash theme={null} curl -X POST "https://api.swarms.world/v1/graph-workflow/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "SEO-Content-Generation-Pipeline", "description": "4-agent SEO content factory", "task": "Generate a publish-ready SEO article for: Acme Corp — AI-powered CRM for B2B SaaS startups. Primary keyword: ai crm for small business", "agents": [ { "agent_name": "ContentAnalyst", "system_prompt": "You are a senior content strategist. Extract company overview, products, audience, value props, brand voice, and content gaps.", "model_name": "gpt-5.4", "max_loops": 1, "temperature": 0.3, "max_tokens": 4000 }, { "agent_name": "KeywordStrategist", "system_prompt": "You are an SEO keyword strategist. Produce primary keyword, secondary keywords, long-tail phrases, LSI terms, search intent mapping, and featured snippet opportunities.", "model_name": "gpt-5.4", "max_loops": 1, "temperature": 0.3, "max_tokens": 4000 }, { "agent_name": "SEOWriter", "system_prompt": "You are an SEO content writer. Write a 1,400-1,800 word article in Markdown using the brand analysis and keyword strategy from previous agents.", "model_name": "gpt-5.4", "max_loops": 1, "temperature": 0.55, "max_tokens": 6000 }, { "agent_name": "SEOPublisher", "system_prompt": "You are an SEO technical editor. Produce: meta tags, JSON-LD schema, heading audit, internal linking suggestions, readability report, and final optimized article.", "model_name": "gpt-5.4", "max_loops": 1, "temperature": 0.3, "max_tokens": 8000 } ], "edges": [ {"source": "ContentAnalyst", "target": "SEOWriter"}, {"source": "KeywordStrategist", "target": "SEOWriter"}, {"source": "SEOWriter", "target": "SEOPublisher"} ], "entry_points": ["ContentAnalyst", "KeywordStrategist"], "end_points": ["SEOPublisher"], "max_loops": 1 }' ``` </Tab> <Tab title="JavaScript (fetch)"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const MODEL = "gpt-5.4"; const workflow = { name: "SEO-Content-Generation-Pipeline", description: "4-agent SEO content factory", task: "Generate a publish-ready SEO article for: Acme Corp — AI-powered CRM for B2B SaaS startups. Primary keyword: 'ai crm for small business'", agents: [ { agent_name: "ContentAnalyst", system_prompt: "You are a senior content strategist. Extract company overview, products, audience, value props, brand voice, and content gaps.", model_name: MODEL, max_loops: 1, temperature: 0.3, max_tokens: 4000, }, { agent_name: "KeywordStrategist", system_prompt: "You are an SEO keyword strategist. Produce primary keyword, secondary keywords, long-tail phrases, LSI terms, search intent mapping, and featured snippet opportunities.", model_name: MODEL, max_loops: 1, temperature: 0.3, max_tokens: 4000, }, { agent_name: "SEOWriter", system_prompt: "You are an SEO content writer. Write a 1,400-1,800 word article in Markdown using the brand analysis and keyword strategy from previous agents.", model_name: MODEL, max_loops: 1, temperature: 0.55, max_tokens: 6000, }, { agent_name: "SEOPublisher", system_prompt: "You are an SEO technical editor. Produce: meta tags, JSON-LD schema, heading audit, internal linking suggestions, readability report, and final optimized article.", model_name: MODEL, max_loops: 1, temperature: 0.3, max_tokens: 8000, }, ], edges: [ { source: "ContentAnalyst", target: "SEOWriter" }, { source: "KeywordStrategist", target: "SEOWriter" }, { source: "SEOWriter", target: "SEOPublisher" }, ], entry_points: ["ContentAnalyst", "KeywordStrategist"], end_points: ["SEOPublisher"], max_loops: 1, }; const response = await fetch( "https://api.swarms.world/v1/graph-workflow/completions", { method: "POST", headers: { "x-api-key": API_KEY, "Content-Type": "application/json" }, body: JSON.stringify(workflow), } ); const result = await response.json(); console.log(result.outputs.SEOPublisher); ``` </Tab> </Tabs> *** ## Customization Guide ### Scaling to Multiple Articles ```python theme={null} targets = [ {"url": "https://yoursite.com/product/crm", "keyword": "ai crm software"}, {"url": "https://yoursite.com/product/email", "keyword": "ai email automation"}, {"url": "https://yoursite.com/product/leads", "keyword": "ai lead generation tool"}, ] for target in targets: source_text, source_label = get_source_content(target.get("url"), None) workflow = build_workflow(source_text, source_label, target.get("keyword", "")) result = run_seo_pipeline(workflow) slug = target["keyword"].replace(" ", "-") save_article(result, f"articles/{slug}.md") print(f"[DONE] Saved article for keyword: {target['keyword']}") ``` ### Adjusting Article Tone ```python theme={null} # For a technical/developer audience "Write in a direct, technically precise voice. Use code snippets where appropriate." # For an executive/business audience "Write in a confident, business-focused voice. Emphasize ROI and strategic value." # For a conversational/consumer audience "Write in a warm, conversational tone. Use 'you' directly. Short paragraphs." ``` ### Adding a Competitor Analysis Agent ```python theme={null} # Add to agents list: { "agent_name": "CompetitorAnalyst", "system_prompt": ( "You are a competitive SEO analyst. Describe what the top 3-5 competitor articles " "on this topic typically cover, what they do well, and what differentiation angles " "a new article could exploit to outrank them." ), "model_name": "gpt-5.4", "max_loops": 1, "temperature": 0.4, "max_tokens": 3000, }, # Add to edges: {"source": "CompetitorAnalyst", "target": "SEOWriter"}, # Replace entry_points with: entry_points = ["ContentAnalyst", "KeywordStrategist", "CompetitorAnalyst"] ``` *** ## Troubleshooting | Issue | Cause | Fix | | --------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------- | | `403 Forbidden` | Free plan account | Upgrade to Pro or Ultra at [swarms.world/platform/account](https://swarms.world/platform/account) | | `timeout` on URL fetch | Target site is slow or blocks bots | Increase `timeout` in `fetch_url_content`, or use `--description` instead | | Empty `SEOPublisher` output | Article exceeded context window | Lower `max_tokens` on `SEOWriter` to 4,000 | | `beautifulsoup4` not found | Missing dependency | Run `pip install beautifulsoup4 lxml` | | `lxml` parser warning | lxml not installed | Run `pip install lxml` or change `"lxml"` to `"html.parser"` | *** ## Related Resources * [Graph Workflow API Reference](/docs/documentation/multi-agent/graph_workflow) * [Graph Workflow Examples](/docs/examples/examples/graph-workflow) * [Sequential Workflow](/docs/documentation/multi-agent/sequential_workflow) * [Concurrent Workflow](/docs/documentation/multi-agent/concurrent_workflow) * [Available Models](/docs/examples/examples/models-available) * [Pricing](/docs/documentation/resources/pricing) # Sequential Workflow Example Source: https://docs.swarms.ai/docs/examples/examples/sequential-workflow Build a legal document review pipeline with SequentialWorkflow ## Legal Document Review Pipeline This example demonstrates how to build a document review system where each agent processes the output of the previous one - perfect for multi-stage processing workflows. ### Step 1: Setup ```python theme={null} import requests import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Define Your Sequential Pipeline Create a 4-stage document review pipeline where each agent builds on the previous agent's work: ```python theme={null} def review_legal_document(document_text: str) -> dict: """Process a legal document through sequential review stages.""" swarm_config = { "name": "Legal Document Review Pipeline", "description": "Sequential legal document review", "swarm_type": "SequentialWorkflow", "task": f"Review this legal document:\n\n{document_text}", "agents": [ { "agent_name": "Document Parser", "description": "Extracts key information from legal documents", "system_prompt": "You are a legal document parser. Extract: document type, parties involved, key dates, financial terms, and obligations for each party.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Risk Analyst", "description": "Identifies potential legal risks", "system_prompt": "You are a legal risk analyst. Based on the parsed document, identify HIGH, MEDIUM, and LOW risk items. Explain each risk and suggest mitigations.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3 }, { "agent_name": "Compliance Checker", "description": "Verifies regulatory compliance", "system_prompt": "You are a compliance specialist. Review the document and risk analysis to check regulatory compliance (GDPR, industry regulations). Provide a compliance score (1-10).", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2 }, { "agent_name": "Summary Generator", "description": "Creates executive summary", "system_prompt": "You are an executive assistant. Create a 2-minute read summary with: document overview, key terms, top 3 risks, compliance status, and recommendation (Sign/Negotiate/Reject).", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4 } ], "max_loops": 1 } response = requests.post( f"{API_BASE_URL}/v1/swarm/completions", headers=headers, json=swarm_config, timeout=120 ) return response.json() ``` ### Step 3: Run the Pipeline ```python theme={null} # Sample contract contract = """ SERVICE AGREEMENT This Agreement is entered into as of January 15, 2025 by and between: Provider: TechCorp Solutions Inc., a Delaware corporation Client: Acme Industries LLC, a California LLC 1. SERVICES: Provider agrees to deliver cloud infrastructure management services. 2. TERM: 36 months, auto-renewing for 12-month periods unless terminated with 30 days notice. 3. FEES: $15,000/month, due within 30 days. Late payments incur 2% monthly interest. 4. LIMITATION OF LIABILITY: Provider's total liability shall not exceed fees paid in preceding 3 months. 5. TERMINATION: Provider may terminate immediately for breach. Client may terminate with 90 days notice and payment of remaining term fees. """ # Run review result = review_legal_document(contract) # Display results for output in result.get("output", []): print(f"\n--- {output['role']} ---") print(output['content'][:500] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") ``` **Expected Output:** ``` --- Document Parser --- Document Type: Service Agreement Parties: TechCorp Solutions Inc. (Provider), Acme Industries LLC (Client) Key Dates: Effective Jan 15, 2025, 36-month term... --- Risk Analyst --- HIGH RISK: Asymmetric termination rights - Client must pay remaining fees to exit... --- Compliance Checker --- Compliance Score: 7/10 Missing: Data processing terms, GDPR provisions... --- Summary Generator --- RECOMMENDATION: NEGOTIATE - Address termination clause before signing... Total cost: $0.0891 ``` <Note> Each agent in SequentialWorkflow receives the previous agent's output. Design your prompts so each stage builds on prior work. </Note> # Streaming Responses Source: https://docs.swarms.ai/docs/examples/examples/streaming Real-time streaming responses for immediate agent feedback <Info> Streaming is enabled by setting `"streaming_on": true` in your agent configuration. </Info> ## Quick Start Enable streaming by adding the `streaming_on` parameter to your agent configuration: <Tabs> <Tab title="Python"> ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" } payload = { "agent_config": { "agent_name": "Creative Writer", "description": "A creative writing specialist", "system_prompt": "You are a creative writer who specializes in storytelling.", "model_name": "gpt-4.1-mini", "max_tokens": 2048, "temperature": 0.8, "streaming_on": True }, "task": "Write a short story about a robot learning to paint" } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, stream=True ) # Process the streaming response for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('data: '): try: data = json.loads(line[6:]) if 'content' in data: print(data['content'], end='', flush=True) except json.JSONDecodeError: continue ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no" }; const payload = { agent_config: { agent_name: "Creative Writer", description: "A creative writing specialist", system_prompt: "You are a creative writer who specializes in storytelling.", model_name: "gpt-4.1-mini", max_tokens: 2048, temperature: 0.8, streaming_on: true }, task: "Write a short story about a robot learning to paint" }; fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }) .then(response => { const reader = response.body.getReader(); const decoder = new TextDecoder(); function readStream() { reader.read().then(({ done, value }) => { if (done) return; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { try { const data = JSON.parse(line.substring(6)); if (data.content) { process.stdout.write(data.content); } } catch (e) { // Skip malformed JSON } } } readStream(); }); } readStream(); }); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -H "Connection: keep-alive" \ -H "X-Accel-Buffering: no" \ -d '{ "agent_config": { "agent_name": "Creative Writer", "model_name": "gpt-4.1-mini", "max_tokens": 2048, "temperature": 0.8, "streaming_on": true }, "task": "Write a short story about a robot learning to paint" }' \ --no-buffer -N ``` </Tab> </Tabs> ## Advanced Configuration For more complex streaming scenarios, you can customize the agent configuration: ## Stream Format The API returns data in Server-Sent Events (SSE) format: ``` data: {"job_id": "abc123", "success": true, "name": "Creative Writer", "description": "A creative writing specialist", "temperature": 0.8, "timestamp": "2026-02-05T00:58:15.121915+00:00", "stream": true, "type": "metadata"} event: start data: {"message": "Starting agent processing..."} event: chunk data: {"content": "Once upon a time", "timestamp": "2026-02-05T00:58:15.200000+00:00"} event: chunk data: {"content": ", in a workshop filled with", "timestamp": "2026-02-05T00:58:15.250000+00:00"} event: usage data: {"input_tokens": 45, "output_tokens": 120, "total_tokens": 165, "img_cost": 0.0, "total_cost": 0.002512} event: end data: {"job_id": "abc123", "usage": {"input_tokens": 45, "output_tokens": 120, "total_tokens": 165, "img_cost": 0.0, "total_cost": 0.002512}, "timestamp": "2026-02-05T00:58:16.000000+00:00", "complete": true} event: done data: {"message": "Agent processing complete"} ``` <Note> The first frame (initial metadata) is sent without an `event:` line, so it arrives as a default `message` event. Only `content` chunks include the `content` key, which is what the example consumer code above checks for. </Note> ## Key Benefits * **Real-time Feedback**: See results as they're generated * **Better User Experience**: Reduced perceived latency * **Progress Tracking**: Monitor long-running operations * **Immediate Error Detection**: Catch issues early in the process ## Use Cases * **Creative Writing**: Generate stories, articles, or content with live updates * **Data Analysis**: Process large datasets with streaming insights * **Research Tasks**: Get research findings as they're discovered * **Code Generation**: See code being written in real-time * **Educational Content**: Create interactive learning experiences # Structured Outputs Example Source: https://docs.swarms.ai/docs/examples/examples/structured-outputs Extract structured JSON data from unstructured text using schema-enforced outputs ## Company Data Extractor This example demonstrates how to extract structured, schema-enforced JSON from unstructured text using `llm_args.response_format` - perfect for data extraction, classification, and form processing. A second approach using `tools_list_dictionary` (OpenAI function-calling schemas) is covered [below](#structured-outputs-via-tools_list_dictionary). ### Step 1: Get Your Swarms API Key 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate a new API key 4. Store it securely in your environment variables ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ### Step 2: Setup ```python theme={null} import requests import json import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 3: Define Your Structured Output Agent Create an agent with a JSON schema that defines the exact fields you want extracted: ```python theme={null} def extract_company_info(text: str) -> dict: """Extract structured company information from unstructured text.""" payload = { "agent_config": { "agent_name": "Company Extractor", "description": "Extracts structured company info from text", "system_prompt": "Extract the requested information from the provided text. Return only the JSON output.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.0, "llm_args": { "response_format": { "type": "json_schema", "json_schema": { "name": "company_info", "strict": True, "schema": { "type": "object", "properties": { "company_name": { "type": "string", "description": "The name of the company" }, "industry": { "type": "string", "description": "The industry the company operates in" }, "founded_year": { "type": "integer", "description": "The year the company was founded" }, "key_products": { "type": "array", "items": {"type": "string"}, "description": "Main products or services" } }, "required": ["company_name", "industry", "founded_year", "key_products"], "additionalProperties": False } } } } }, "task": text } response = requests.post( f"{API_BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60 ) return response.json() ``` ### Step 4: Run the Extraction ```python theme={null} # Sample unstructured text text = """ Anthropic is an AI safety company founded in 2021 by Dario Amodei and Daniela Amodei. They are known for building Claude, a family of large language models, and for their research on AI alignment and interpretability. The company is based in San Francisco and has raised over $7 billion in funding. """ # Run extraction result = extract_company_info(text) # Parse the structured output content = result["outputs"][0]["content"] company_info = json.loads(content) print(json.dumps(company_info, indent=2)) ``` **Expected Output:** ```json theme={null} { "company_name": "Anthropic", "industry": "Artificial Intelligence / AI Safety", "founded_year": 2021, "key_products": [ "Claude", "AI alignment research", "AI interpretability research" ] } ``` <Note> The schema uses `"strict": true` and `"additionalProperties": false` to guarantee the response matches your schema exactly. Every field in `required` will always be present in the output. </Note> *** ## Structured Outputs via `tools_list_dictionary` A second way to get structured output is the `tools_list_dictionary` field on the agent config (`Optional[List[Dict]]` on `AgentSpec`). Instead of constraining the response format, you give the agent one or more OpenAI function-calling-style JSON schemas. The model responds by "calling" your function, and the arguments it passes are JSON that conforms to your `parameters` schema — effectively schema-enforced output. Each entry in `tools_list_dictionary` follows the OpenAI function calling format: ```json theme={null} { "type": "function", "function": { "name": "function_name", "description": "What this function does", "parameters": { "type": "object", "properties": { "...": "..." }, "required": ["..."] } } } ``` ### Example: Sentiment Classifier This agent classifies customer feedback by "calling" a `record_sentiment` function whose arguments are the structured result. <CodeGroup> ```python Python theme={null} import requests import json import os API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Sentiment Classifier", "description": "Classifies customer feedback into structured sentiment data", "system_prompt": "You are a sentiment analysis expert. Analyze the provided feedback and record your findings using the record_sentiment function.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 4096, "temperature": 0.0, "tools_list_dictionary": [ { "type": "function", "function": { "name": "record_sentiment", "description": "Record the sentiment analysis of a piece of customer feedback", "parameters": { "type": "object", "properties": { "sentiment": { "type": "string", "enum": ["positive", "negative", "neutral", "mixed"], "description": "Overall sentiment of the feedback" }, "confidence": { "type": "number", "description": "Confidence score between 0 and 1" }, "topics": { "type": "array", "items": {"type": "string"}, "description": "Topics mentioned in the feedback" }, "requires_followup": { "type": "boolean", "description": "Whether the feedback needs a human follow-up" } }, "required": ["sentiment", "confidence", "topics", "requires_followup"] } } } ] }, "task": "The checkout flow was confusing and I was double-charged, but support refunded me quickly and was very friendly." } response = requests.post( f"{API_BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60 ) result = response.json() # The agent's tool call arguments are the structured output tool_calls = result["outputs"][0]["content"] for tool_call in tool_calls: arguments = json.loads(tool_call["function"]["arguments"]) print(json.dumps(arguments, indent=2)) ``` ```bash cURL theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Sentiment Classifier", "description": "Classifies customer feedback into structured sentiment data", "system_prompt": "You are a sentiment analysis expert. Analyze the provided feedback and record your findings using the record_sentiment function.", "model_name": "gpt-4.1", "max_loops": 1, "max_tokens": 4096, "temperature": 0.0, "tools_list_dictionary": [ { "type": "function", "function": { "name": "record_sentiment", "description": "Record the sentiment analysis of a piece of customer feedback", "parameters": { "type": "object", "properties": { "sentiment": { "type": "string", "enum": ["positive", "negative", "neutral", "mixed"], "description": "Overall sentiment of the feedback" }, "confidence": { "type": "number", "description": "Confidence score between 0 and 1" }, "topics": { "type": "array", "items": {"type": "string"}, "description": "Topics mentioned in the feedback" }, "requires_followup": { "type": "boolean", "description": "Whether the feedback needs a human follow-up" } }, "required": ["sentiment", "confidence", "topics", "requires_followup"] } } } ] }, "task": "The checkout flow was confusing and I was double-charged, but support refunded me quickly and was very friendly." }' ``` </CodeGroup> **Expected Response:** When the agent uses a tool, `outputs[0].content` is an array of tool call objects. The `function.arguments` field is a JSON string that matches your `parameters` schema: ```json theme={null} { "job_id": "agent-8c2f4c1de5a94b0f9d3e6a7b1c2d3e4f", "success": true, "name": "Sentiment Classifier", "outputs": [ { "role": "Sentiment Classifier", "content": [ { "function": { "arguments": "{\"sentiment\":\"mixed\",\"confidence\":0.92,\"topics\":[\"checkout flow\",\"billing\",\"customer support\"],\"requires_followup\":true}", "name": "record_sentiment" }, "id": "call_x7YkQm2nPfWv4RzLbTe9AhGd", "type": "function" } ] } ], "usage": { "input_tokens": 132, "output_tokens": 58, "total_tokens": 190, "total_cost": 0.00073 } } ``` The parsed `arguments` give you the structured result: ```json theme={null} { "sentiment": "mixed", "confidence": 0.92, "topics": ["checkout flow", "billing", "customer support"], "requires_followup": true } ``` <Note> `function.arguments` is a **JSON string**, not a parsed object — decode it with `json.loads()` (Python) or `JSON.parse()` (JavaScript) before use. </Note> ### Which approach should I use? | | `llm_args.response_format` | `tools_list_dictionary` | | ----------------------- | ----------------------------------------------------------------------- | ------------------------------------------------- | | Enforces schema on | The response text itself | The function call arguments | | Best for | Pure data extraction and classification | Function calling, routing, and structured actions | | Response `content` type | JSON string | Array of tool call objects | | Model support | Models with native structured-output support (e.g. `gpt-4.1`, `gpt-4o`) | Any model with function calling | Both fields can be set on the same agent. For a deeper guide to tools and function calling, see [Structured Outputs & Tools](/docs/documentation/capabilities/swarms_api_tools). # Sub-Agent Delegation Example Source: https://docs.swarms.ai/docs/examples/examples/sub-agent-delegation Build a market analysis system where a coordinator agent dynamically creates and delegates to specialized sub-agents ## Parallel Market Analysis with Sub-Agents This example demonstrates how a single coordinator agent can dynamically create specialized sub-agents and delegate parallel research tasks — perfect for complex analyses that benefit from domain-specific expertise. ### What This Example Shows * Enabling sub-agent delegation with `max_loops="auto"` * How the coordinator autonomously creates and assigns work to sub-agents * Parallel execution across multiple research domains * Result aggregation into a unified report ### How Sub-Agents Work Unlike [agent handoffs](/docs/examples/examples/agent-handoffs) where specialist agents are pre-defined in your request, sub-agents are **created dynamically at runtime** by the coordinator. The coordinator decides how many agents to create and what each one specializes in. ### Step 1: Setup ```python theme={null} import requests import os import json API_BASE_URL = "https://api.swarms.world" API_KEY = os.environ.get("SWARMS_API_KEY", "your_api_key_here") headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } ``` ### Step 2: Configure the Coordinator Agent The coordinator agent needs `max_loops="auto"` to enable autonomous tool use, including `create_sub_agent` and `assign_task`: ```python theme={null} def analyze_market(company: str) -> dict: """Run a parallel market analysis using sub-agent delegation.""" payload = { "agent_config": { "agent_name": "Market-Analysis-Coordinator", "description": "Senior market analyst that coordinates parallel research streams", "system_prompt": ( "You are a senior market analyst coordinating a research team. " "For each analysis request:\n" "1. Create specialized sub-agents for each research domain\n" "2. Assign specific research tasks to each sub-agent\n" "3. Wait for all results and compile a comprehensive market report\n\n" "Always create at least 3 sub-agents covering: " "financial analysis, competitive landscape, and industry trends." ), "model_name": "gpt-4.1", "max_loops": "auto", "max_tokens": 8192, "temperature": 0.3 }, "task": ( f"Conduct a comprehensive market analysis for {company}. " "Create specialized sub-agents and delegate the following research areas:\n" "1. Financial Analysis: Revenue trends, profitability, key financial metrics\n" "2. Competitive Landscape: Major competitors, market share, differentiation\n" "3. Industry Trends: Market growth, emerging technologies, regulatory changes\n" "4. Risk Assessment: Key risks, vulnerabilities, mitigation strategies\n\n" "Compile all findings into a structured executive briefing." ) } response = requests.post( f"{API_BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=300 ) return response.json() ``` ### Step 3: Run the Analysis ```python theme={null} result = analyze_market("Tesla Inc.") if result.get("success"): print(f"Agent: {result['name']}") print(f"Output:\n{result['outputs'][:2000]}...") else: print(f"Error: {result}") ``` **Expected Behavior:** The coordinator will autonomously: 1. **Create sub-agents** — e.g., "Financial-Analyst", "Competition-Researcher", "Industry-Trends-Analyst", "Risk-Assessor" 2. **Assign tasks** — Each sub-agent receives a focused research task 3. **Execute in parallel** — Sub-agents run concurrently 4. **Compile results** — The coordinator synthesizes all findings into a unified report <Note> Sub-agent workflows take longer than single-agent calls since multiple agents are created and run. Use a timeout of 300 seconds or more for complex delegation tasks. </Note> ## Next Steps * [Sub-Agent Delegation Reference](/docs/documentation/capabilities/sub_agents) — Full documentation on sub-agent tools and parameters * [Autonomous Agent Tutorial](/docs/examples/api_examples/autonomous_agent_tutorial) — Learn the autonomous mode that powers sub-agents * [HierarchicalSwarm](/docs/documentation/multi-agent/hierarchical_swarm) — Pre-defined multi-agent hierarchy for known team structures # Supply Chain Hierarchical Swarm Source: https://docs.swarms.ai/docs/examples/examples/supply-chain-swarm A hierarchical swarm of logistics, inventory, and procurement specialists coordinated by a Supply Chain Director. ## What This Example Shows * A `HierarchicalSwarm` applied to a real-world business analysis problem * A director coordinating three domain specialists (logistics, inventory, procurement) * How to write director and worker system prompts that compose cleanly <Info> This is the same hierarchical pattern as the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow), applied to supply chain analysis instead of software development. Swap the worker roles and prompts to apply it to any domain — legal review, M\&A due diligence, clinical case conferences, marketing campaign planning. </Info> ## Step 1: Setup ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = os.getenv("SWARMS_BASE_URL", "https://api.swarms.world") headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define the Team The director sets strategy and synthesizes. Each specialist owns one functional area. ```python theme={null} payload = { "name": "Supply Chain Hierarchical Swarm", "description": "Director coordinates logistics, inventory, and procurement specialists.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( "Analyze the current supply chain challenges facing the semiconductor " "industry and provide optimization recommendations for a mid-sized " "electronics manufacturer. Consider:\n" "1. Current supply chain bottlenecks and disruptions\n" "2. Inventory management strategies during shortages\n" "3. Supplier diversification opportunities\n" "4. Long-term resilience improvements" ), "agents": [ { "agent_name": "Supply Chain Director", "description": "Oversees strategy and synthesizes specialist outputs.", "system_prompt": ( "You are a Supply Chain Director with extensive global experience. " "Coordinate analysis across logistics, inventory, and procurement. " "Identify bottlenecks, develop optimization strategies, and ensure " "resilience and risk mitigation. Synthesize your team's input into " "actionable strategic recommendations." ), "model_name": "gpt-4.1", "role": "coordinator", "max_loops": 1, "max_tokens": 8192, "temperature": 0.3, }, { "agent_name": "Logistics Specialist", "description": "Transportation and distribution optimization.", "system_prompt": ( "You are a Logistics Specialist. Focus on transportation modes, " "route planning, distribution network design, last-mile delivery, " "and freight cost optimization. Provide detailed analysis with " "improvement recommendations." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, }, { "agent_name": "Inventory Manager", "description": "Stock optimization and demand forecasting.", "system_prompt": ( "You are an Inventory Management expert. Focus on demand " "forecasting, inventory optimization, safety stock, warehouse " "utilization, and carrying-cost reduction. Provide data-driven " "recommendations." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, }, { "agent_name": "Procurement Analyst", "description": "Supplier management and strategic sourcing.", "system_prompt": ( "You are a Procurement Analyst. Focus on supplier evaluation, " "sourcing strategy, vendor diversification, contract negotiation, " "and supplier risk assessment. Balance cost efficiency with " "supply reliability." ), "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, }, ], } ``` ## Step 3: Run the Swarm ```python theme={null} response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) result = response.json() for output in result.get("output", []): print("=" * 60) print(output["role"]) print("=" * 60) content = output["content"] if isinstance(content, list): content = " ".join(str(c) for c in content) print(str(content)[:400] + "...") print(f"\nTotal cost: ${result['usage']['billing_info']['total_cost']:.4f}") print(f"Execution time: {result['execution_time']:.1f}s") ``` <Note> The director sees every specialist's output and writes the final synthesis. Workers do not see each other's drafts. Design your director prompt around "review, decide, recommend" — not "write a long report." </Note> ## Adapting the Pattern Replace the three specialists to retarget the swarm: | Domain | Director | Workers | | -------------------------------- | ------------------- | ------------------------------------------------------ | | **M\&A due diligence** | Deal Lead | Financial Analyst, Legal Counsel, Technical Auditor | | **Clinical case conference** | Attending Physician | Radiologist, Pathologist, Cardiologist | | **Marketing campaign** | Brand Director | Copywriter, Designer, Performance Marketer | | **Software architecture review** | Principal Engineer | Backend Engineer, Database Engineer, Security Engineer | Everything else — the request shape, the response shape, the billing — stays identical. # Swarm Logs & API History Source: https://docs.swarms.ai/docs/examples/examples/swarm-logs Access and analyze your API request logs and swarm execution history Access comprehensive logs of all your API requests and swarm executions. The `/v1/account/logs` endpoint provides detailed information about your API usage history, including request timestamps, status codes, and execution details. (The older `/v1/swarm/logs` path is a deprecated alias for the same endpoint.) <Info> Logs are filtered to exclude any entries containing client IP addresses for privacy protection. Access is limited to logs associated with your API key. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } def get_swarm_logs(): """Get all API request logs""" response = requests.get( f"{BASE_URL}/v1/account/logs", headers=headers ) if response.status_code == 200: return response.json() else: print(f"Error: {response.status_code} - {response.text}") return None # Get logs logs_data = get_swarm_logs() if logs_data: print("✅ Logs retrieved successfully!") print(f"Total logs: {len(logs_data.get('logs', []))}") print(json.dumps(logs_data, indent=2)) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getSwarmLogs() { try { const response = await fetch(`${BASE_URL}/v1/account/logs`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Logs retrieved successfully!"); console.log(`Total logs: ${(data.logs || []).length}`); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error('Error:', error); return null; } } // Get logs getSwarmLogs(); ``` </Tab> <Tab title="cURL"> ```bash theme={null} # Get API request logs curl -X GET "https://api.swarms.world/v1/account/logs" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" # Example response: # { # "status": "success", # "count": 137, # "logs": [ # { # "id": 12345, # "created_at": "2026-07-01T10:30:00+00:00", # "api_key": "...a1b2", # "category": "completion", # "data": { # "job_id": "agent-abc123", # "success": true, # "name": "Research Assistant", # "usage": { # "input_tokens": 45, # "output_tokens": 120, # "total_tokens": 165, # "total_cost": 0.002735 # }, # "timestamp": "2026-07-01T10:30:00+00:00" # } # } # ], # "timestamp": "2026-07-01T12:00:00+00:00" # } ``` </Tab> </Tabs> ## Understanding Log Response The logs endpoint returns structured information about your API usage. Each log entry is a stored record with a `category` (e.g. `completion`) and a `data` payload containing the completion response that was logged: ```json theme={null} { "status": "success", "count": 137, "logs": [ { "id": 12345, "created_at": "2026-07-01T10:30:00+00:00", "api_key": "...a1b2", "category": "completion", "data": { "job_id": "agent-abc123", "success": true, "name": "Research Assistant", "description": "An agent that researches topics", "temperature": 0.5, "outputs": "...", "usage": { "input_tokens": 45, "output_tokens": 120, "total_tokens": 165, "img_cost": 0.0, "total_cost": 0.002735 }, "timestamp": "2026-07-01T10:30:00+00:00" } } ], "timestamp": "2026-07-01T12:00:00+00:00" } ``` <Note> The top-level `count` is the exact total number of matching log entries across every API key on the account, including revoked ones. It is not `len(logs)`: the `logs` array is capped at the 1000 newest entries, so `count` exceeds it once an account passes 1000 requests. Each entry's `api_key` is redacted to its last 4 characters. The shape of `data` depends on what was logged: agent completions carry `usage.total_cost`, while swarm completions carry `usage.billing_info.total_cost`, `swarm_name`, and `execution_time`. Entries containing client IP data, telemetry, and raw request inputs are excluded. </Note> ## Log Analysis and Filtering <Tabs> <Tab title="Python"> ```python theme={null} from datetime import datetime, timedelta, timezone from collections import Counter def get_log_usage(log): """Extract the usage dict from a log entry's data payload.""" data = log.get('data') or {} if isinstance(data, dict): return data.get('usage') or {} return {} def get_log_cost(log): """Extract total cost from a log entry (agent or swarm completion).""" usage = get_log_usage(log) if 'total_cost' in usage: return usage['total_cost'] or 0 # Swarm completions nest the cost under billing_info return (usage.get('billing_info') or {}).get('total_cost', 0) def analyze_logs(logs_data): """Analyze API usage logs""" if not logs_data or not logs_data.get('logs'): print("No logs available for analysis") return logs = logs_data['logs'] # Basic statistics total_requests = len(logs) print("📊 API Usage Analysis") print("=" * 50) print(f"Total Logged Requests: {total_requests}") print() # Category usage (e.g. "completion") category_counts = Counter(log.get('category', 'unknown') for log in logs) print("🔗 Category Usage:") for category, count in category_counts.most_common(): print(f" {category}: {count} requests") print() # Cost analysis total_cost = sum(get_log_cost(log) for log in logs) total_tokens = sum(get_log_usage(log).get('total_tokens', 0) for log in logs) print("💰 Cost Analysis:") print(f" Total Cost: ${total_cost:.4f}") print(f" Total Tokens: {total_tokens}") avg_cost = total_cost / total_requests if total_requests else 0 print(f" Average Cost per Request: ${avg_cost:.4f}") print() # Execution time analysis (present on swarm completion logs) execution_times = [ log['data'].get('execution_time') for log in logs if isinstance(log.get('data'), dict) and log['data'].get('execution_time') ] if execution_times: avg_execution_time = sum(execution_times) / len(execution_times) max_execution_time = max(execution_times) min_execution_time = min(execution_times) print("⏱️ Execution Time Analysis:") print(f" Average: {avg_execution_time:.2f}s") print(f" Max: {max_execution_time:.2f}s") print(f" Min: {min_execution_time:.2f}s") def filter_logs_by_date(logs_data, days=7): """Filter logs by date range""" if not logs_data or not logs_data.get('logs'): return logs_data cutoff_date = datetime.now(timezone.utc) - timedelta(days=days) filtered_logs = [] for log in logs_data['logs']: log_timestamp = datetime.fromisoformat(log['created_at'].replace('Z', '+00:00')) if log_timestamp >= cutoff_date: filtered_logs.append(log) return { **logs_data, 'logs': filtered_logs, 'count': len(filtered_logs) } def filter_logs_by_category(logs_data, categories): """Filter logs by category (e.g. ["completion"])""" if not logs_data or not logs_data.get('logs'): return logs_data filtered_logs = [ log for log in logs_data['logs'] if log.get('category') in categories ] return { **logs_data, 'logs': filtered_logs, 'count': len(filtered_logs) } # Example usage logs_data = get_swarm_logs() if logs_data: # Analyze all logs analyze_logs(logs_data) # Filter for last 7 days recent_logs = filter_logs_by_date(logs_data, days=7) print(f"\n📅 Recent Logs (7 days): {recent_logs['count']} requests") # Filter for completions completion_logs = filter_logs_by_category(logs_data, ["completion"]) print(f"✅ Completion Logs: {completion_logs['count']} requests") ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} function getLogUsage(log) { const data = log.data || {}; return data.usage || {}; } function getLogCost(log) { const usage = getLogUsage(log); if (usage.total_cost !== undefined) return usage.total_cost || 0; // Swarm completions nest the cost under billing_info return (usage.billing_info || {}).total_cost || 0; } function analyzeLogs(logsData) { if (!logsData || !logsData.logs) { console.log("No logs available for analysis"); return; } const logs = logsData.logs; // Basic statistics const totalRequests = logs.length; console.log("📊 API Usage Analysis"); console.log("=".repeat(50)); console.log(`Total Logged Requests: ${totalRequests}`); console.log(); // Category usage (e.g. "completion") const categoryCounts = {}; logs.forEach(log => { const category = log.category || 'unknown'; categoryCounts[category] = (categoryCounts[category] || 0) + 1; }); console.log("🔗 Category Usage:"); Object.entries(categoryCounts) .sort(([,a], [,b]) => b - a) .forEach(([category, count]) => { console.log(` ${category}: ${count} requests`); }); console.log(); // Cost analysis const totalCost = logs.reduce((sum, log) => sum + getLogCost(log), 0); const totalTokens = logs.reduce((sum, log) => sum + (getLogUsage(log).total_tokens || 0), 0); console.log("💰 Cost Analysis:"); console.log(` Total Cost: $${totalCost.toFixed(4)}`); console.log(` Total Tokens: ${totalTokens}`); console.log(` Avg Cost per Request: $${(totalCost/totalRequests).toFixed(6)}`); console.log(); } function filterLogsByDate(logsData, days = 7) { if (!logsData || !logsData.logs) return logsData; const cutoffDate = new Date(Date.now() - (days * 24 * 60 * 60 * 1000)); const filteredLogs = logsData.logs.filter(log => { const logTimestamp = new Date(log.created_at); return logTimestamp >= cutoffDate; }); return { ...logsData, logs: filteredLogs, count: filteredLogs.length }; } function filterLogsByCategory(logsData, categories) { if (!logsData || !logsData.logs) return logsData; const filteredLogs = logsData.logs.filter(log => categories.includes(log.category) ); return { ...logsData, logs: filteredLogs, count: filteredLogs.length }; } // Example usage getSwarmLogs().then(logsData => { if (logsData) { // Analyze all logs analyzeLogs(logsData); // Filter for last 7 days const recentLogs = filterLogsByDate(logsData, 7); console.log(`\n📅 Recent Logs (7 days): ${recentLogs.count} requests`); // Filter for completions const completionLogs = filterLogsByCategory(logsData, ["completion"]); console.log(`✅ Completion Logs: ${completionLogs.count} requests`); } }); ``` </Tab> </Tabs> ## Log Export and Backup <Tabs> <Tab title="Python"> ```python theme={null} import csv import json from datetime import datetime def export_logs_to_csv(logs_data, filename=None): """Export logs to CSV format""" if not logs_data or not logs_data.get('logs'): print("No logs to export") return if not filename: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"swarm_logs_{timestamp}.csv" logs = logs_data['logs'] # Define CSV columns fieldnames = [ 'id', 'created_at', 'category', 'job_id', 'name', 'input_tokens', 'output_tokens', 'total_tokens', 'total_cost' ] with open(filename, 'w', newline='', encoding='utf-8') as csvfile: writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() for log in logs: # Flatten the nested data payload data = log.get('data') or {} if not isinstance(data, dict): data = {} usage = data.get('usage') or {} total_cost = usage.get('total_cost') if total_cost is None: total_cost = (usage.get('billing_info') or {}).get('total_cost', '') row = { 'id': log.get('id', ''), 'created_at': log.get('created_at', ''), 'category': log.get('category', ''), 'job_id': data.get('job_id', ''), 'name': data.get('name', data.get('swarm_name', '')), 'input_tokens': usage.get('input_tokens', ''), 'output_tokens': usage.get('output_tokens', ''), 'total_tokens': usage.get('total_tokens', ''), 'total_cost': total_cost } writer.writerow(row) print(f"✅ Logs exported to {filename}") return filename def export_logs_to_json(logs_data, filename=None): """Export logs to JSON format""" if not logs_data: print("No logs to export") return if not filename: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"swarm_logs_{timestamp}.json" with open(filename, 'w', encoding='utf-8') as jsonfile: json.dump(logs_data, jsonfile, indent=2, ensure_ascii=False) print(f"✅ Logs exported to {filename}") return filename def create_log_backup(logs_data, compress=True): """Create a compressed backup of logs""" import gzip if not logs_data: return timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"swarm_logs_backup_{timestamp}.json" if compress: filename += '.gz' with gzip.open(filename, 'wt', encoding='utf-8') as f: json.dump(logs_data, f, indent=2, ensure_ascii=False) else: with open(filename, 'w', encoding='utf-8') as f: json.dump(logs_data, f, indent=2, ensure_ascii=False) print(f"✅ Backup created: {filename}") return filename # Example usage logs_data = get_swarm_logs() if logs_data: # Export to different formats export_logs_to_csv(logs_data) export_logs_to_json(logs_data) create_log_backup(logs_data, compress=True) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} function exportLogsToCSV(logsData, filename = null) { if (!logsData || !logsData.logs) { console.log("No logs to export"); return; } if (!filename) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5); filename = `swarm_logs_${timestamp}.csv`; } const logs = logsData.logs; const headers = ['id', 'created_at', 'category', 'job_id', 'name', 'input_tokens', 'output_tokens', 'total_tokens', 'total_cost']; let csvContent = headers.join(',') + '\n'; logs.forEach(log => { const data = log.data || {}; const usage = data.usage || {}; const totalCost = usage.total_cost !== undefined ? usage.total_cost : (usage.billing_info || {}).total_cost || ''; const row = [ log.id || '', log.created_at || '', log.category || '', data.job_id || '', data.name || data.swarm_name || '', usage.input_tokens || '', usage.output_tokens || '', usage.total_tokens || '', totalCost ]; csvContent += row.map(field => `"${field}"`).join(',') + '\n'; }); // Download CSV (browser environment) const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; link.click(); console.log(`✅ Logs exported to ${filename}`); return filename; } function exportLogsToJSON(logsData, filename = null) { if (!logsData) { console.log("No logs to export"); return; } if (!filename) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5); filename = `swarm_logs_${timestamp}.json`; } const jsonContent = JSON.stringify(logsData, null, 2); // Download JSON (browser environment) const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; link.click(); console.log(`✅ Logs exported to ${filename}`); return filename; } // Example usage getSwarmLogs().then(logsData => { if (logsData) { exportLogsToCSV(logsData); exportLogsToJSON(logsData); } }); ``` </Tab> </Tabs> ## Log Monitoring Dashboard <Tabs> <Tab title="Python"> ```python theme={null} import time from datetime import datetime, timedelta, timezone class LogMonitor: def __init__(self, check_interval=300): # 5 minutes default self.check_interval = check_interval self.last_log_count = 0 self.cost_accumulator = 0 def monitor_logs(self): """Monitor logs continuously""" print("🚀 Starting log monitoring... (Press Ctrl+C to stop)") try: while True: logs_data = get_swarm_logs() if logs_data: self.analyze_recent_activity(logs_data) self.check_for_anomalies(logs_data) time.sleep(self.check_interval) except KeyboardInterrupt: print("\n⏹️ Monitoring stopped") self.generate_monitoring_report() def analyze_recent_activity(self, logs_data): """Analyze recent API activity""" if not logs_data.get('logs'): return current_count = len(logs_data.get('logs', [])) if self.last_log_count > 0: new_logs = current_count - self.last_log_count if new_logs > 0: print(f"📈 {new_logs} new requests in the last {self.check_interval}s") self.last_log_count = current_count # Analyze recent logs (last hour) recent_logs = self.get_recent_logs(logs_data, hours=1) if recent_logs: # Cost analysis (uses the get_log_cost helper defined above) recent_cost = sum(get_log_cost(log) for log in recent_logs) self.cost_accumulator += recent_cost print(f"💵 Recent cost: ${recent_cost:.4f}") print(f"💵 Total accumulated cost: ${self.cost_accumulator:.4f}") def check_for_anomalies(self, logs_data): """Check for unusual patterns or anomalies""" if not logs_data.get('logs'): return recent_logs = self.get_recent_logs(logs_data, hours=1) if recent_logs: # Check for unusual execution times (swarm completion logs) execution_times = [ log['data'].get('execution_time') for log in recent_logs if isinstance(log.get('data'), dict) and log['data'].get('execution_time') ] if execution_times: avg_execution_time = sum(execution_times) / len(execution_times) if avg_execution_time > 60: # More than 60 seconds average print(f"🐢 Slow swarm runs detected: {avg_execution_time:.2f}s average") def get_recent_logs(self, logs_data, hours=1): """Get logs from the last N hours""" if not logs_data.get('logs'): return [] cutoff_time = datetime.now(timezone.utc) - timedelta(hours=hours) recent_logs = [] for log in logs_data['logs']: log_time = datetime.fromisoformat(log['created_at'].replace('Z', '+00:00')) if log_time >= cutoff_time: recent_logs.append(log) return recent_logs def generate_monitoring_report(self): """Generate a final monitoring report""" print("\n📊 Monitoring Report") print("=" * 50) print(f"Total Accumulated Cost: ${self.cost_accumulator:.4f}") print(f"Monitoring Duration: {self.check_interval}s intervals") # Usage monitor = LogMonitor(check_interval=300) # Check every 5 minutes monitor.monitor_logs() ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} class LogMonitor { constructor(checkInterval = 300000) { // 5 minutes default this.checkInterval = checkInterval; this.lastLogCount = 0; this.costAccumulator = 0; this.isMonitoring = false; } async startMonitoring() { console.log("🚀 Starting log monitoring... (Call stopMonitoring() to stop)"); this.isMonitoring = true; while (this.isMonitoring) { try { const logsData = await getSwarmLogs(); if (logsData) { await this.analyzeRecentActivity(logsData); this.checkForAnomalies(logsData); } } catch (error) { console.error("Monitoring error:", error); } await new Promise(resolve => setTimeout(resolve, this.checkInterval)); } } stopMonitoring() { this.isMonitoring = false; console.log("⏹️ Monitoring stopped"); this.generateMonitoringReport(); } async analyzeRecentActivity(logsData) { if (!logsData.logs) return; const currentCount = (logsData.logs || []).length; if (this.lastLogCount > 0) { const newLogs = currentCount - this.lastLogCount; if (newLogs > 0) { console.log(`📈 ${newLogs} new requests in the last ${this.checkInterval/1000}s`); } } this.lastLogCount = currentCount; // Analyze recent logs (last hour) const recentLogs = this.getRecentLogs(logsData, 1); if (recentLogs.length > 0) { // Cost analysis (uses the getLogCost helper defined above) const recentCost = recentLogs.reduce((sum, log) => sum + getLogCost(log), 0); this.costAccumulator += recentCost; console.log(`💰 Recent Cost (1h): $${recentCost.toFixed(4)}`); console.log(`💰 Total Accumulated Cost: $${this.costAccumulator.toFixed(4)}`); } } checkForAnomalies(logsData) { if (!logsData.logs) return; const recentLogs = this.getRecentLogs(logsData, 1); if (recentLogs.length === 0) return; // Check for unusual execution times (swarm completion logs) const executionTimes = recentLogs .map(log => (log.data || {}).execution_time) .filter(t => t); if (executionTimes.length > 0) { const avgExecutionTime = executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length; if (avgExecutionTime > 60) { // More than 60 seconds average console.log(`🐢 Slow swarm runs detected: ${avgExecutionTime.toFixed(2)}s average`); } } } getRecentLogs(logsData, hours = 1) { if (!logsData.logs) return []; const cutoffTime = new Date(Date.now() - (hours * 60 * 60 * 1000)); return logsData.logs.filter(log => { const logTime = new Date(log.created_at); return logTime >= cutoffTime; }); } generateMonitoringReport() { console.log("\n📊 Monitoring Report"); console.log("=".repeat(50)); console.log(`Total Accumulated Cost: $${this.costAccumulator.toFixed(4)}`); } } // Usage const monitor = new LogMonitor(300000); // Check every 5 minutes monitor.startMonitoring(); // Stop after 30 minutes setTimeout(() => { monitor.stopMonitoring(); }, 30 * 60 * 1000); ``` </Tab> </Tabs> ## Privacy and Security ### Data Protection * **IP Address Filtering**: All client IP addresses are automatically filtered from logs * **PII Protection**: Personal identifiable information is not logged * **Secure Storage**: Logs are stored securely with encryption at rest * **Access Control**: Only accessible via your API key ### Compliance * **GDPR Compliant**: Adheres to data protection regulations * **Audit Trail**: Maintains complete audit trail of API usage * **Data Retention**: Logs retained for compliance and debugging purposes * **Access Logging**: All log access is itself logged for security ## Best Practices ### Log Management 1. **Regular Monitoring**: Check logs regularly for unusual patterns 2. **Error Analysis**: Investigate error spikes promptly 3. **Cost Tracking**: Monitor API costs and optimize usage 4. **Performance Analysis**: Track response times and identify bottlenecks 5. **Security Monitoring**: Watch for unauthorized access attempts ### Data Analysis 1. **Trend Analysis**: Identify usage patterns and growth trends 2. **Error Pattern Recognition**: Detect recurring issues 3. **Cost Optimization**: Find opportunities to reduce API costs 4. **Performance Optimization**: Identify slow endpoints and optimize 5. **Capacity Planning**: Plan for future usage growth ### Automation 1. **Alert Setup**: Set up alerts for high error rates or costs 2. **Automated Reports**: Generate regular usage reports 3. **Anomaly Detection**: Automatically detect unusual patterns 4. **Cost Controls**: Implement automatic cost limiting 5. **Performance Monitoring**: Continuous performance tracking ## Troubleshooting ### Common Issues **Empty Logs Response** ```bash theme={null} # Check if API key is correct curl -I "https://api.swarms.world/v1/account/logs" \ -H "x-api-key: your-api-key" ``` **Missing Log Entries** * Logs are filtered for privacy (no IP addresses) * Some requests may not be logged due to high volume * Check your API key permissions **Performance Issues** ```python theme={null} # Analyze execution time patterns (present on swarm completion logs) logs_data = get_swarm_logs() if logs_data: execution_times = [ log['data']['execution_time'] for log in logs_data['logs'] if isinstance(log.get('data'), dict) and log['data'].get('execution_time') ] if execution_times: avg_time = sum(execution_times) / len(execution_times) print(f"Average execution time: {avg_time:.2f}s") ``` **Cost Analysis** ```python theme={null} # Calculate cost per log category (uses the get_log_cost helper defined above) from collections import defaultdict category_costs = defaultdict(float) for log in logs_data['logs']: category_costs[log.get('category', 'unknown')] += get_log_cost(log) for category, cost in sorted(category_costs.items(), key=lambda x: x[1], reverse=True): print(f"{category}: ${cost:.4f}") ``` # Streaming Tokens from Multi-Agent Swarms Source: https://docs.swarms.ai/docs/examples/examples/swarm-streaming Stream individual tokens from every agent in a SequentialWorkflow or AgentRearrange swarm in real time, including detecting parallel-phase interleaving. ## What This Example Shows * How to enable swarm-level streaming with `stream: true` on `/v1/swarm/completions` * The full SSE event taxonomy for swarms: `metadata`, `agent_start`, `chunk`, `agent_end`, `usage`, `end` * How to parse the SSE stream into typed events with agent attribution on every chunk * How to detect parallel-phase interleaving in `AgentRearrange` (when two agents stream concurrently) * Why this differs from single-agent streaming on `/v1/agent/completions` <Info> Single-agent streaming (covered in [Streaming Responses](/docs/examples/examples/streaming)) streams one model's tokens. Swarm streaming is harder: tokens come from multiple agents, sometimes overlapping in time. Every chunk carries an `agent` field so you know which worker produced it. </Info> ## Why This Matters Multi-agent swarms are powerful but feel slow without streaming — users stare at a spinner while three agents take turns thinking. Per-token swarm streaming fixes that: the moment any agent in the pipeline starts producing output, you can render it. For `SequentialWorkflow` this gives a "live whiteboard" of one agent finishing before the next picks up. For `AgentRearrange` with a parallel phase (`A, B -> C`), it gives the truly novel experience of watching two agents type simultaneously into the same UI, then a third synthesize their output the moment they finish. This unlocks chat-style UX for swarm products instead of the batch-job UX you get from non-streaming calls. ## Step 1: Setup ```python theme={null} import json import os import time import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" # X-Accel-Buffering: no disables proxy buffering so tokens flush immediately. headers = { "x-api-key": API_KEY, "Content-Type": "application/json", "Connection": "keep-alive", "X-Accel-Buffering": "no", } ``` ## Step 2: Understand the SSE Event Types When `stream=true` is set on a `SequentialWorkflow` or `AgentRearrange` swarm, the API responds with a Server-Sent Events stream. Each event has an `event:` line and a `data:` JSON payload. | Event | Emitted | Payload (key fields) | | ------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `metadata` | Once, at the start | `job_id`, `swarm_name`, `swarm_type`, `number_of_agents` | | `start` | Once, before agents run | Swarm-level status | | `agent_start` | Once per agent, when it begins | `agent` (name) | | `chunk` | Many per agent — one per token (or small group) | `agent`, `content` (the token text) | | `agent_end` | Once per agent, when it finishes | `agent` (final per-agent content is not included in this event — collect it from the `chunk` events) | | `usage` | Once, near the end | `input_tokens`, `output_tokens`, `total_tokens`, `billing_info` | | `end` | Once, terminal | `execution_time`, `status` (does not include the aggregated output — collect it from the `chunk`/`agent_end` events as you stream) | <Note> The defining feature of swarm streaming is that **every `chunk` event carries an `agent` field**. That's how you attribute a token to the correct worker when multiple agents are running. Single-agent streaming on `/v1/agent/completions` does not need this — there is only one agent. </Note> ## Step 3: A Reusable SSE Parser This helper turns the raw stream into a list of `{event, data, received_at}` dicts. The `received_at` timestamp is what lets you detect interleaving in the parallel case. (This mirrors the parser in the test suite — see `tests/test_sequential_streaming.py` and `tests/test_rearrange_streaming.py`.) ```python theme={null} def parse_sse_events(response): """Parse an SSE stream into a list of {event, data, received_at} dicts.""" events = [] current_event = None for line in response.iter_lines(decode_unicode=True): if line is None: continue if line.startswith("event:"): current_event = line[len("event:"):].strip() elif line.startswith("data:"): raw = line[len("data:"):].strip() try: data = json.loads(raw) except json.JSONDecodeError: data = {"raw": raw} events.append({ "event": current_event or "message", "data": data, "received_at": time.perf_counter(), }) current_event = None elif line == "": current_event = None return events ``` ## Step 4: Stream a `SequentialWorkflow` In a sequential swarm, agents run one after another. Tokens from agent A all arrive before any tokens from agent B. You'll see this clearly in the chunk stream — the `agent` field on each chunk stays constant for a long run, then flips to the next agent and stays there. ```python theme={null} def make_agent(name, system_prompt): return { "agent_name": name, "system_prompt": system_prompt, "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, } def stream_sequential(): payload = { "name": "streaming-sequential-example", "swarm_type": "SequentialWorkflow", "task": "List two short bullets about solid-state batteries.", "stream": True, "max_loops": 1, "agents": [ make_agent("Researcher", "List two short bullets on the topic."), make_agent("Writer", "Combine the bullets into one short paragraph."), ], } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, stream=True, timeout=120, ) response.raise_for_status() current_agent = None event_name = None for line in response.iter_lines(decode_unicode=True): if not line: continue if line.startswith("event:"): event_name = line[len("event:"):].strip() continue if line.startswith("data:"): try: data = json.loads(line[len("data:"):].strip()) except json.JSONDecodeError: continue if event_name == "agent_start": current_agent = data.get("agent") print(f"\n\n--- {current_agent} starting ---") elif event_name == "chunk": token = data.get("content") or "" print(token, end="", flush=True) elif event_name == "agent_end": print(f"\n--- {data.get('agent')} done ---") elif event_name == "usage": print(f"\n[usage] total_tokens={data.get('total_tokens')}") elif event_name == "end": elapsed = data.get("execution_time") print(f"\n[end] {elapsed:.2f}s" if elapsed else "\n[end]") if __name__ == "__main__": stream_sequential() ``` You'll see the Researcher's tokens stream out completely, then the Writer's tokens. No overlap — that's the contract of `SequentialWorkflow`. ## Step 5: Stream `AgentRearrange` and Detect Parallel Interleaving `AgentRearrange` lets you express a flow with parallel branches using the syntax `"A, B -> C"` — A and B run concurrently, then C runs after both finish. With streaming on, you'll see A's and B's tokens *interleaved* in the chunk stream. Detecting that interleaving is how you confirm parallel execution. ```python theme={null} def stream_rearrange_and_detect_interleaving(): payload = { "name": "streaming-rearrange-example", "swarm_type": "AgentRearrange", "rearrange_flow": "Optimist, Pessimist -> Summary", "task": "AI in healthcare", "stream": True, "max_loops": 1, "agents": [ make_agent("Optimist", "Write 4-6 upbeat sentences about the topic. Be detailed."), make_agent("Pessimist", "Write 4-6 cautious sentences about the topic. Be detailed."), make_agent("Summary", "Write one short summary line of the prior views."), ], } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, stream=True, timeout=120, ) response.raise_for_status() events = parse_sse_events(response) chunk_events = [e for e in events if e["event"] == "chunk"] # Look only at the parallel-phase agents. parallel_agents_seen = [ e["data"].get("agent") for e in chunk_events if e["data"].get("agent") in ("Optimist", "Pessimist") ] # A "flip" is consecutive chunks coming from different agents. flips = sum( 1 for i in range(1, len(parallel_agents_seen)) if parallel_agents_seen[i] != parallel_agents_seen[i - 1] ) print(f"Optimist chunks: {parallel_agents_seen.count('Optimist')}") print(f"Pessimist chunks: {parallel_agents_seen.count('Pessimist')}") print(f"Agent flips during parallel phase: {flips}") if flips >= 3: print("Interleaving confirmed — Optimist and Pessimist streamed concurrently.") else: print("No interleaving detected — agents ran sequentially.") ``` A high `flips` count is your signal that the parallel branch is actually parallel. After both finish, the `Summary` agent's chunks will follow in a single contiguous run. <Note> This is the same detection logic used in the test suite. See `tests/test_rearrange_streaming.py` for the canonical reference — it asserts `flips >= 3` to verify true parallel streaming. </Note> ## Step 6: Rendering Chunks Per-Agent in a UI In a real UI you want each agent's tokens to land in its own panel even when they interleave. The pattern is to bucket chunks by `agent` and append: ```python theme={null} def render_per_agent(response): panels: dict[str, str] = {} current_event = None for line in response.iter_lines(decode_unicode=True): if not line: continue if line.startswith("event:"): current_event = line[len("event:"):].strip() elif line.startswith("data:"): data = json.loads(line[len("data:"):].strip()) if current_event == "agent_start": panels[data["agent"]] = "" elif current_event == "chunk": agent = data.get("agent", "unknown") panels[agent] = panels.get(agent, "") + (data.get("content") or "") # In a real UI, push (agent, content) into a websocket / SSE here. elif current_event == "end": break return panels ``` The interleaved chunk stream becomes N independent, growing text buffers — exactly what a multi-panel chat UI needs. <AccordionGroup> <Accordion title="Which swarm types support `stream=true`?"> Per-token streaming is currently supported for `SequentialWorkflow` and `AgentRearrange`. Other swarm types either don't expose per-token output or stream at the agent level only — check `/v1/swarms/available` for the current list. </Accordion> <Accordion title="Why isn't my stream actually streaming?"> Two common causes: (1) you forgot `stream=True` on the `requests.post` call (the API streams but your client buffers the whole response), or (2) a reverse proxy is buffering. Set `X-Accel-Buffering: no` in your request headers and make sure your client reads with `response.iter_lines()`, not `response.text`. </Accordion> <Accordion title="How do I know when an individual agent is finished vs. the whole swarm?"> `agent_end` fires once per agent. `end` fires once for the entire swarm after the last agent finishes and usage is reported. If you want to update per-agent UI state, key off `agent_end`; if you want to dismiss a global spinner, key off `end`. </Accordion> </AccordionGroup> ## Next Steps * [Streaming Responses](/docs/examples/examples/streaming) — the single-agent counterpart on `/v1/agent/completions` * [Sequential Workflow](/docs/examples/examples/sequential-workflow) — the non-streaming version of the swarm type used above * [Multi-Turn Conversations with Agent History](/docs/examples/examples/conversation-history) — pair streaming with history threading for live chat UX # Available Swarm Types Source: https://docs.swarms.ai/docs/examples/examples/swarm-types Discover all available swarm architectures and choose the right one for your use case Explore all available swarm architectures supported by the Swarms API. The `/v1/swarms/available` endpoint provides information about different swarm types, their capabilities, and use cases. <Info> Different swarm types are optimized for different workflows - choose the right architecture for your specific needs. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import json import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } def get_swarm_types(): """Get all available swarm types""" response = requests.get( f"{BASE_URL}/v1/swarms/available", headers=headers ) if response.status_code == 200: return response.json() else: print(f"Error: {response.status_code} - {response.text}") return None # Get swarm types swarm_data = get_swarm_types() if swarm_data: print("✅ Swarm types retrieved successfully!") print(json.dumps(swarm_data, indent=2)) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getSwarmTypes() { try { const response = await fetch(`${BASE_URL}/v1/swarms/available`, { method: 'GET', headers: headers }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("✅ Swarm types retrieved successfully!"); console.log(JSON.stringify(data, null, 2)); return data; } catch (error) { console.error('Error:', error); return null; } } // Get swarm types getSwarmTypes(); ``` </Tab> <Tab title="cURL"> ```bash theme={null} # Get available swarm types curl -X GET "https://api.swarms.world/v1/swarms/available" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" # Example response: # { # "status": true, # "timestamp": "2026-07-13T19:37:41.821232", # "swarm_types": [ # "AgentRearrange", # "MixtureOfAgents", # "SequentialWorkflow", # "ConcurrentWorkflow", # "GroupChat", # "MultiAgentRouter", # "HierarchicalSwarm", # "auto", # "MajorityVoting", # "CouncilAsAJudge", # "HeavySwarm", # "BatchedGridWorkflow", # "LLMCouncil", # "DebateWithJudge", # "RoundRobin", # "PlannerWorkerSwarm" # ] # } ``` </Tab> </Tabs> ## Swarm Type Selection Guide ### For Different Use Cases <Tabs> <Tab title="Complex Problem Solving"> ```python theme={null} # Use MixtureOfAgents for diverse expertise swarm_config = { "name": "Research Swarm", "description": "Multi-disciplinary research team", "agents": [ { "agent_name": "Data Analyst", "model_name": "gpt-4.1", "role": "analyst" }, { "agent_name": "Domain Expert", "model_name": "gpt-4.1", "role": "expert" } ], "swarm_type": "MixtureOfAgents", "task": "Analyze market trends and provide strategic recommendations" } ``` </Tab> <Tab title="Step-by-Step Processes"> ```python theme={null} # Use SequentialWorkflow for ordered tasks swarm_config = { "name": "Content Creation Pipeline", "description": "Structured content creation process", "agents": [ { "agent_name": "Researcher", "model_name": "gpt-4.1-mini", "role": "research" }, { "agent_name": "Writer", "model_name": "gpt-4.1", "role": "writing" }, { "agent_name": "Editor", "model_name": "gpt-4.1-mini", "role": "editing" } ], "swarm_type": "SequentialWorkflow", "task": "Create a comprehensive article about AI ethics" } ``` </Tab> <Tab title="Parallel Processing"> ```python theme={null} # Use ConcurrentWorkflow for independent tasks swarm_config = { "name": "Data Processing Swarm", "description": "Parallel data analysis", "agents": [ { "agent_name": "Data Processor 1", "model_name": "gpt-4.1-mini" }, { "agent_name": "Data Processor 2", "model_name": "gpt-4.1-mini" }, { "agent_name": "Data Processor 3", "model_name": "gpt-4.1-mini" } ], "swarm_type": "ConcurrentWorkflow", "tasks": [ "Process dataset A", "Process dataset B", "Process dataset C" ] } ``` </Tab> <Tab title="Dynamic Optimization"> ```python theme={null} # Use AgentRearrange for adaptive workflows swarm_config = { "name": "Adaptive Analysis Swarm", "description": "Self-optimizing agent arrangement", "agents": [ { "agent_name": "Primary Analyst", "model_name": "gpt-4.1" }, { "agent_name": "Secondary Analyst", "model_name": "gpt-4.1-mini" } ], "swarm_type": "AgentRearrange", "rearrange_flow": "Primary Analyst -> Secondary Analyst", "task": "Analyze complex business data" } ``` </Tab> </Tabs> ## Swarm Type Comparison The `/v1/swarms/available` endpoint currently returns 16 swarm types: | Swarm Type | Best For | Execution | Complexity | Scalability | | ----------------------- | ----------------------------------------------------- | ------------ | ---------- | ----------- | | **AgentRearrange** | Adaptive workflows, optimization | Dynamic | High | Medium | | **MixtureOfAgents** | Complex problems, diverse expertise | Parallel | High | High | | **SequentialWorkflow** | Step-by-step processes, pipelines | Sequential | Medium | Medium | | **ConcurrentWorkflow** | Independent tasks, batch processing | Parallel | Low | High | | **GroupChat** | Collaborative discussions, brainstorming | Interactive | Medium | Low | | **MultiAgentRouter** | Routing tasks to the best-suited agent | Dynamic | Medium | High | | **HierarchicalSwarm** | Structured organizations, management | Hierarchical | High | Medium | | **auto** | Letting the API pick the best swarm type for the task | Dynamic | Low | Medium | | **MajorityVoting** | Consensus-driven decisions | Parallel | Medium | Medium | | **CouncilAsAJudge** | Multi-perspective evaluation and judging | Parallel | High | Low | | **HeavySwarm** | Large-scale, high-effort research and analysis | Hybrid | High | Medium | | **BatchedGridWorkflow** | Running many agent/task combinations at once | Parallel | Medium | High | | **LLMCouncil** | Panel-style deliberation across multiple models | Parallel | High | Low | | **DebateWithJudge** | Adversarial debate resolved by a judge agent | Sequential | High | Low | | **RoundRobin** | Rotating a task through agents in turn | Sequential | Low | Medium | | **PlannerWorkerSwarm** | Planner agent delegating to worker agents | Hierarchical | Medium | Medium | ## Advanced Swarm Configuration <Tabs> <Tab title="Hierarchical Swarm"> ```python theme={null} swarm_config = { "name": "Corporate Analysis Department", "description": "Hierarchical corporate structure", "agents": [ { "agent_name": "CEO Agent", "model_name": "gpt-4.1", "role": "executive" }, { "agent_name": "Manager Agent", "model_name": "gpt-4.1", "role": "manager" }, { "agent_name": "Analyst Agent 1", "model_name": "gpt-4.1-mini", "role": "analyst" }, { "agent_name": "Analyst Agent 2", "model_name": "gpt-4.1-mini", "role": "analyst" } ], "swarm_type": "HierarchicalSwarm", "task": "Conduct comprehensive market analysis" } ``` </Tab> <Tab title="Group Chat Swarm"> ```python theme={null} swarm_config = { "name": "Brainstorming Session", "description": "Interactive group discussion", "agents": [ { "agent_name": "Moderator", "model_name": "gpt-4.1", "role": "moderator" }, { "agent_name": "Creative Thinker", "model_name": "gpt-4.1", "role": "creative" }, { "agent_name": "Technical Expert", "model_name": "gpt-4.1", "role": "technical" }, { "agent_name": "Business Analyst", "model_name": "gpt-4.1-mini", "role": "business" } ], "swarm_type": "GroupChat", "messages": [ {"role": "user", "content": "Let's brainstorm innovative product ideas"}, {"role": "user", "content": "What are the technical challenges?"}, {"role": "user", "content": "How can we monetize this?"} ], "task": "Brainstorm and evaluate new product concepts" } ``` </Tab> </Tabs> ## Swarm Performance Optimization <Tabs> <Tab title="Load Balancing"> ```python theme={null} def optimize_swarm_for_load(tasks, available_resources): """Optimize swarm configuration based on load""" task_count = len(tasks) resource_count = len(available_resources) if task_count > resource_count * 2: # High load - run every task in parallel via the "tasks" list return { "swarm_type": "ConcurrentWorkflow", "tasks": tasks } elif task_count > resource_count: # Medium load - use mixture of agents return { "swarm_type": "MixtureOfAgents" } else: # Low load - use sequential for quality return { "swarm_type": "SequentialWorkflow" } ``` </Tab> <Tab title="Cost Optimization"> ```python theme={null} def optimize_swarm_for_cost(task_complexity, budget_limit): """Optimize swarm for cost efficiency""" # model_name and max_tokens are per-agent settings — apply them to # every entry in the payload's "agents" list. if budget_limit < 0.1: # Very low budget return { "swarm_type": "ConcurrentWorkflow", "agents": [ {"agent_name": "Worker", "model_name": "gpt-4.1-mini", "max_tokens": 512} ] } elif budget_limit < 0.5: # Medium budget return { "swarm_type": "SequentialWorkflow", "agents": [ {"agent_name": "Worker", "model_name": "gpt-4.1-mini"} ] } else: # High budget return { "swarm_type": "MixtureOfAgents", "agents": [ {"agent_name": "Expert", "model_name": "gpt-4.1"} ] } ``` </Tab> <Tab title="Quality Optimization"> ```python theme={null} def optimize_swarm_for_quality(requirements): """Optimize swarm for maximum quality""" if requirements.get("consensus_required"): # Use an odd number of agents in the payload's "agents" list # so MajorityVoting can always reach a decision return { "swarm_type": "MajorityVoting" } elif requirements.get("iterative_improvement"): return { "swarm_type": "AgentRearrange", "max_loops": 3 } else: return { "swarm_type": "MixtureOfAgents" } ``` </Tab> </Tabs> ## Best Practices ### Swarm Design 1. **Match Type to Task**: Choose swarm type based on your specific requirements 2. **Agent Diversity**: Use diverse agents with different expertise areas 3. **Clear Roles**: Define clear roles and responsibilities for each agent 4. **Communication Protocols**: Establish clear communication patterns ### Performance Optimization 1. **Resource Allocation**: Allocate resources based on task complexity 2. **Load Balancing**: Distribute work evenly across agents 3. **Monitoring**: Monitor swarm performance and adjust configuration 4. **Scalability**: Design swarms that can scale with increased load ### Quality Assurance 1. **Testing**: Test swarm configurations with sample tasks 2. **Validation**: Validate outputs against expected results 3. **Feedback Loops**: Implement feedback mechanisms for improvement 4. **Version Control**: Track swarm configuration versions ### Cost Management 1. **Model Selection**: Choose appropriate models based on task requirements 2. **Resource Limits**: Set appropriate limits to control costs 3. **Usage Monitoring**: Monitor resource usage and costs 4. **Optimization**: Continuously optimize for cost efficiency # Function Tools in Multi-Agent Swarms Source: https://docs.swarms.ai/docs/examples/examples/tools-in-swarms Attach OpenAI-style function tools to agents inside a multi-agent swarm. ## What This Example Shows * How to pass `tools_list_dictionary` on a per-agent basis inside a swarm * How the same tool schema can be shared across multiple worker agents * A `ConcurrentWorkflow` of two financial analysts that both call a structured `search_topic` tool <Info> Every multi-agent architecture on Swarms accepts the same per-agent `tools_list_dictionary`. The pattern below works identically for `SequentialWorkflow`, `HierarchicalSwarm`, `AgentRearrange`, `GroupChat`, `MixtureOfAgents`, and the rest — only the `swarm_type` changes. </Info> ## Step 1: Setup ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Define a Shared Tool Schema Tools follow the OpenAI function-call schema. Define it once and reuse across agents. ```python theme={null} SEARCH_TOOL = { "type": "function", "function": { "name": "search_topic", "description": ( "Conduct an in-depth search on a specified topic, generating a " "comprehensive array of highly detailed search queries." ), "parameters": { "type": "object", "properties": { "depth": { "type": "integer", "description": ( "Level of thoroughness, 1 (superficial) to 3 (deep)." ), }, "detailed_queries": { "type": "array", "description": "Specific search queries for the topic.", "items": {"type": "string"}, }, }, "required": ["depth", "detailed_queries"], }, }, } ``` ## Step 3: Build the Swarm Two analysts run concurrently, each equipped with the same tool. Each agent independently decides when to call `search_topic`. ```python theme={null} def run_financial_swarm() -> dict: payload = { "name": "Financial Analysis Swarm", "description": "Two analysts research markets in parallel using a shared search tool.", "swarm_type": "ConcurrentWorkflow", "max_loops": 1, "task": "What are the best ETFs and index funds for AI and tech?", "agents": [ { "agent_name": "Market Analyst", "description": "Analyzes market trends.", "system_prompt": "You are a financial analyst expert.", "model_name": "openai/gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [SEARCH_TOOL], }, { "agent_name": "Economic Forecaster", "description": "Predicts economic trends.", "system_prompt": "You are an expert in economic forecasting.", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 8192, "temperature": 0.5, "tools_list_dictionary": [SEARCH_TOOL], }, ], } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) return response.json() ``` ## Step 4: Run It ```python theme={null} result = run_financial_swarm() print(json.dumps(result, indent=2)) ``` <Note> Tools are scoped per-agent, not per-swarm. You can give each worker its own toolset — for example, the Market Analyst could get a `search_topic` tool while the Economic Forecaster gets a different `fetch_macro_data` tool. The swarm orchestrator does not need to know about either. </Note> ## Reuse the Pattern To switch to a different swarm topology, only `swarm_type` changes: | Goal | `swarm_type` | | ---------------------------------------- | -------------------- | | Run analysts in parallel | `ConcurrentWorkflow` | | Chain them one after the other | `SequentialWorkflow` | | Have a director synthesize their output | `HierarchicalSwarm` | | Route the task to whichever analyst fits | `MultiAgentRouter` | | Vote on the best answer | `MajorityVoting` | The `tools_list_dictionary` on each agent stays exactly the same. # Usage Report Source: https://docs.swarms.ai/docs/examples/examples/usage-report Retrieve daily usage breakdowns with token counts, request counts, and costs from the /v1/usage/report endpoint Retrieve a daily breakdown of your API usage from the `/v1/usage/report` endpoint. The report includes token consumption, request counts, and costs for each day in the requested period. <Warning> `GET /v1/usage/report` is not yet live on the production API — it exists only on an unmerged feature branch. Calling it against `https://api.swarms.world` will currently return a 404. For live per-operation pricing, use [`/v1/usage/costs`](/docs/examples/examples/pricing-details-basic) instead. </Warning> <Info> The endpoint supports predefined periods (`day`, `week`, `month`) and custom date ranges via `start_date` and `end_date` query parameters. See the [API Reference](/docs/documentation/resources/usage-report) for the full schema. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } def get_usage_report(period: str = "month") -> dict | None: """Fetch a daily usage report for the given period.""" resp = requests.get( f"{BASE_URL}/v1/usage/report", headers=headers, params={"period": period}, ) if resp.status_code == 200: return resp.json() print(f"Error: {resp.status_code} - {resp.text}") return None if __name__ == "__main__": data = get_usage_report("week") if data: print(f"Period: {data['period']}") print(f"Range: {data['start_date']} to {data['end_date']}") print(f"Days with activity: {len(data['results'])}\n") for day in data["results"]: print( f" {day['day']}: " f"cost=${day['total_cost']:.4f}, " f"in={day['input_tokens']:,}, " f"out={day['output_tokens']:,}, " f"reqs={day['request_count']}" ) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function getUsageReport(period = "month") { try { const response = await fetch( `${BASE_URL}/v1/usage/report?period=${period}`, { method: "GET", headers } ); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log(`Period: ${data.period}`); console.log(`Range: ${data.start_date} to ${data.end_date}`); console.log(`Days with activity: ${data.results.length}\n`); for (const day of data.results) { console.log( ` ${day.day}: ` + `cost=$${day.total_cost.toFixed(4)}, ` + `in=${day.input_tokens.toLocaleString()}, ` + `out=${day.output_tokens.toLocaleString()}, ` + `reqs=${day.request_count}` ); } return data; } catch (error) { console.error("Error fetching usage report:", error); return null; } } getUsageReport("week"); ``` </Tab> <Tab title="TypeScript"> ```typescript theme={null} import "dotenv/config"; const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; if (!API_KEY) { throw new Error("SWARMS_API_KEY is not set"); } interface UsageReportDay { day: string; total_cost: number; input_tokens: number; output_tokens: number; request_count: number; } interface UsageReportOutput { results: UsageReportDay[]; period: string; start_date: string; end_date: string; timestamp: string; } async function getUsageReport( period: string = "month" ): Promise<UsageReportOutput | null> { const res = await fetch( `${BASE_URL}/v1/usage/report?period=${period}`, { method: "GET", headers: { "x-api-key": API_KEY, "Content-Type": "application/json", }, } ); if (!res.ok) { const text = await res.text(); throw new Error(`HTTP ${res.status}: ${text}`); } const data = (await res.json()) as UsageReportOutput; console.log(`Period: ${data.period}`); console.log(`Range: ${data.start_date} to ${data.end_date}`); console.log(`Days with activity: ${data.results.length}\n`); for (const day of data.results) { console.log( ` ${day.day}: cost=$${day.total_cost.toFixed(4)}, ` + `in=${day.input_tokens.toLocaleString()}, ` + `out=${day.output_tokens.toLocaleString()}, ` + `reqs=${day.request_count}` ); } return data; } void getUsageReport("week").catch(console.error); ``` </Tab> <Tab title="Rust"> ```rust theme={null} use std::env; use reqwest::blocking::Client; use serde::Deserialize; #[derive(Debug, Deserialize)] struct UsageReportDay { day: String, total_cost: f64, input_tokens: u64, output_tokens: u64, request_count: u64, } #[derive(Debug, Deserialize)] struct UsageReportOutput { results: Vec<UsageReportDay>, period: String, start_date: String, end_date: String, timestamp: String, } fn main() -> Result<(), Box<dyn std::error::Error>> { let api_key = env::var("SWARMS_API_KEY") .expect("SWARMS_API_KEY environment variable is required"); let client = Client::new(); let response = client .get("https://api.swarms.world/v1/usage/report?period=week") .header("x-api-key", &api_key) .header("Content-Type", "application/json") .send()?; let data: UsageReportOutput = response.json()?; println!("Period: {}", data.period); println!("Range: {} to {}", data.start_date, data.end_date); println!("Days with activity: {}\n", data.results.len()); for day in &data.results { println!( " {}: cost=${:.4}, in={}, out={}, reqs={}", day.day, day.total_cost, day.input_tokens, day.output_tokens, day.request_count, ); } Ok(()) } ``` </Tab> <Tab title="Go"> ```go theme={null} package main import ( "encoding/json" "fmt" "log" "net/http" "os" ) type UsageReportDay struct { Day string `json:"day"` TotalCost float64 `json:"total_cost"` InputTokens int `json:"input_tokens"` OutputTokens int `json:"output_tokens"` RequestCount int `json:"request_count"` } type UsageReportOutput struct { Results []UsageReportDay `json:"results"` Period string `json:"period"` StartDate string `json:"start_date"` EndDate string `json:"end_date"` Timestamp string `json:"timestamp"` } func main() { apiKey := os.Getenv("SWARMS_API_KEY") if apiKey == "" { log.Fatal("SWARMS_API_KEY environment variable is required") } req, err := http.NewRequest("GET", "https://api.swarms.world/v1/usage/report?period=week", nil) if err != nil { log.Fatal(err) } req.Header.Set("x-api-key", apiKey) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() var data UsageReportOutput if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { log.Fatal(err) } fmt.Printf("Period: %s\n", data.Period) fmt.Printf("Range: %s to %s\n", data.StartDate, data.EndDate) fmt.Printf("Days with activity: %d\n\n", len(data.Results)) for _, day := range data.Results { fmt.Printf(" %s: cost=$%.4f, in=%d, out=%d, reqs=%d\n", day.Day, day.TotalCost, day.InputTokens, day.OutputTokens, day.RequestCount, ) } } ``` </Tab> <Tab title="cURL"> ```bash theme={null} # Last 30 days (default) curl -X GET "https://api.swarms.world/v1/usage/report" \ -H "x-api-key: $SWARMS_API_KEY" # Last 7 days curl -X GET "https://api.swarms.world/v1/usage/report?period=week" \ -H "x-api-key: $SWARMS_API_KEY" # Custom date range curl -X GET "https://api.swarms.world/v1/usage/report?start_date=2026-03-01&end_date=2026-03-31" \ -H "x-api-key: $SWARMS_API_KEY" ``` </Tab> </Tabs> ## Custom Date Range Pass `start_date` and `end_date` as query parameters to query a specific window. These override the `period` parameter. ```python theme={null} def get_usage_for_march(): """Fetch usage for a specific month.""" resp = requests.get( f"{BASE_URL}/v1/usage/report", headers=headers, params={ "start_date": "2026-03-01", "end_date": "2026-03-31", }, ) data = resp.json() total_cost = sum(d["total_cost"] for d in data["results"]) total_reqs = sum(d["request_count"] for d in data["results"]) print(f"March 2026: ${total_cost:.2f} across {total_reqs:,} requests") ``` ## Monitor Usage Over Time Build a simple cost tracker that alerts on high-usage days: ```python theme={null} def check_daily_spend(threshold: float = 5.0): """Alert if any day in the past week exceeded a cost threshold.""" data = get_usage_report("week") if not data: return for day in data["results"]: if day["total_cost"] > threshold: print( f"High spend on {day['day']}: " f"${day['total_cost']:.2f} " f"({day['request_count']} requests)" ) check_daily_spend(threshold=2.0) ``` ## Response Schema ### UsageReportOutput | Field | Type | Description | | ------------ | -------- | ------------------------------------------------------- | | `results` | `list` | Daily usage entries, sorted ascending by date | | `period` | `string` | The period applied: `day`, `week`, `month`, or `custom` | | `start_date` | `string` | Report start date (`YYYY-MM-DD`) | | `end_date` | `string` | Report end date (`YYYY-MM-DD`) | | `timestamp` | `string` | ISO timestamp when the report was generated | ### UsageReportDay | Field | Type | Description | | --------------- | --------- | ---------------------------- | | `day` | `string` | Date (`YYYY-MM-DD`) | | `total_cost` | `number` | Total cost in USD | | `input_tokens` | `integer` | Total input tokens consumed | | `output_tokens` | `integer` | Total output tokens consumed | | `request_count` | `integer` | Total API requests | ## Related Documentation * [Usage Report API Reference](/docs/documentation/resources/usage-report) — full endpoint specification * [Get Credit Balance](/docs/examples/examples/account-credits) — check your current balance * [Pricing Details](/docs/examples/examples/pricing-details-basic) — per-operation costs * [Rate Limits](/docs/examples/api_examples/rate_limits) — rate limit status # Vision Capabilities Source: https://docs.swarms.ai/docs/examples/examples/vision-capabilities Enable agents to process and analyze images for visual understanding The Swarms API supports vision-enabled agents that can analyze and understand images. This guide shows you how to send a base64-encoded image to an agent and ask it to identify the location. <Info> In this example, we'll send an image of Hong Kong to an agent and ask "What city is this?" </Info> ## Step 1: Get Your API Key Before you can use the Swarms API, you need to obtain an API key. 1. Visit [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Sign in or create an account 3. Generate a new API key 4. Copy and save your API key securely <Note> Keep your API key secure and never commit it to version control. Use environment variables to store it. </Note> ## Step 2: Prepare Your Image (Base64 Encoding) The Swarms API accepts images as base64-encoded strings. Here's how to convert an image to base64: <Tabs> <Tab title="Python"> ```python theme={null} import base64 import requests # Method 1: From a URL hong_kong_url = "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto" response = requests.get(hong_kong_url) base64_image = base64.b64encode(response.content).decode('utf-8') print(f"Base64 string length: {len(base64_image)}") print(f"First 100 characters: {base64_image[:100]}...") # Method 2: From a local file with open("path/to/image.jpg", "rb") as image_file: base64_image = base64.b64encode(image_file.read()).decode('utf-8') ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} // Method 1: From a URL (Node.js) async function encodeImageFromUrl(imageUrl) { const response = await fetch(imageUrl); const buffer = await response.arrayBuffer(); return Buffer.from(buffer).toString('base64'); } // Method 2: From a local file (Node.js) const fs = require('fs'); function encodeImageFromFile(imagePath) { const imageBuffer = fs.readFileSync(imagePath); return imageBuffer.toString('base64'); } // Example: Encode Hong Kong image const hongKongUrl = "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto"; const base64Image = await encodeImageFromUrl(hongKongUrl); console.log(`Base64 string length: ${base64Image.length}`); console.log(`First 100 characters: ${base64Image.substring(0, 100)}...`); ``` </Tab> <Tab title="Bash/cURL"> ```bash theme={null} # From a URL curl -s "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto" | base64 > hongkong_base64.txt # From a local file base64 -i /path/to/image.jpg > image_base64.txt # View first 100 characters head -c 100 hongkong_base64.txt ``` </Tab> </Tabs> ## Step 3: Send the Image to the Agent Now that you have your API key and base64-encoded image, you can send it to the Swarms API. <Tabs> <Tab title="Python"> ```python theme={null} import requests import base64 import os # Step 1: Set your API key API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" # Step 2: Encode the Hong Kong image to base64 hong_kong_url = "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto" img_response = requests.get(hong_kong_url) base64_image = base64.b64encode(img_response.content).decode('utf-8') # Step 3: Prepare the API request headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Vision Analyst", "description": "AI agent with image analysis capabilities", "system_prompt": "You are a vision analyst that can identify and describe images accurately.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.5 }, "task": "What city is this?", "img": base64_image } # Make the API request response = requests.post(f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload) result = response.json() # Display the result print("Agent Response:") print(result['outputs'][0]['content']) # Output: "This city is Hong Kong." ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; // Encode the Hong Kong image from Step 2 const hongKongUrl = "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto"; async function analyzeImage() { // Fetch and encode the image const imageResponse = await fetch(hongKongUrl); const arrayBuffer = await imageResponse.arrayBuffer(); const base64Image = Buffer.from(arrayBuffer).toString('base64'); // Prepare the payload const payload = { agent_config: { agent_name: "Vision Analyst", description: "AI agent with image analysis capabilities", system_prompt: "You are a vision analyst that can identify and describe images accurately.", model_name: "gpt-4.1", max_tokens: 2048, temperature: 0.5 }, task: "What city is this?", img: base64Image }; // Make the API request const response = await fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }); const result = await response.json(); console.log("Agent Response:"); console.log(result.outputs[0].content); // Expected output: "This image is of Hong Kong. The skyline, Victoria Harbour..." } analyzeImage(); ``` </Tab> <Tab title="cURL"> ```bash theme={null} # First, encode the image to base64 BASE64_IMAGE=$(curl -s "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto" | base64) # Make the API request curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key-here" \ -H "Content-Type: application/json" \ -d "{ \"agent_config\": { \"agent_name\": \"Vision Analyst\", \"description\": \"AI agent with image analysis capabilities\", \"system_prompt\": \"You are a vision analyst that can identify and describe images accurately.\", \"model_name\": \"gpt-4.1\", \"max_tokens\": 2048, \"temperature\": 0.5 }, \"task\": \"What city is this?\", \"img\": \"${BASE64_IMAGE}\" }" ``` </Tab> </Tabs> ## Expected Response ```json theme={null} { "job_id": "agent-09a9c0f9ba19419abf64f5538b4b7d59", "success": true, "name": "Vision Analyst", "description": "AI agent with image analysis capabilities", "temperature": 0.5, "outputs": [ { "role": "Vision Analyst", "content": "This image is of Hong Kong. The skyline, Victoria Harbour, and the distinctive tall buildings such as the International Finance Centre (IFC) and International Commerce Centre (ICC) are prominent features of Hong Kong.", "timestamp": "2026-02-05T00:58:15.121915", "message_id": "85b70f9d-e281-4a98-b9ad-5a2d39f8ffcb" } ], "usage": { "input_tokens": 57, "output_tokens": 101, "total_tokens": 158, "img_cost": 0.25, "total_cost": 0.252239 }, "timestamp": "2026-02-05T00:58:15.252392+00:00" } ``` ## Complete Working Example Here's a complete Python script you can run: ```python theme={null} import requests import base64 import os # Step 1: Set your API key API_KEY = os.getenv("SWARMS_API_KEY") if not API_KEY: print("Error: Please set SWARMS_API_KEY environment variable") print("Get your API key at: https://swarms.world/platform/api-keys") exit(1) # Step 2: Encode the Hong Kong image to base64 print("Encoding image...") hong_kong_url = "https://ik.imgkit.net/3vlqs5axxjf/external/ik-seo/http://images.ntmllc.com/v4/destination/Hong-Kong/Hong-Kong-city/112086_SCN_HongKong_iStock466733790_Z8C705/Hong-Kong-Scenery.jpg?tr=w-680%2Ch-404%2Cfo-auto" img_response = requests.get(hong_kong_url) base64_image = base64.b64encode(img_response.content).decode('utf-8') print(f"✓ Image encoded (length: {len(base64_image)} characters)") # Step 3: Send to Swarms API print("\nAnalyzing image with AI agent...") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Vision Analyst", "description": "AI agent with image analysis capabilities", "system_prompt": "You are a vision analyst that can identify and describe images accurately.", "model_name": "gpt-4.1", "max_tokens": 2048, "temperature": 0.5 }, "task": "What city is this?", "img": base64_image } response = requests.post(f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload) result = response.json() # Display results print("\n" + "="*60) print("AGENT RESPONSE:") print("="*60) print(result['outputs'][0]['content']) print("\n" + "="*60) print("USAGE STATS:") print("="*60) print(f"Total tokens: {result['usage']['total_tokens']}") print(f"Image cost: ${result['usage']['img_cost']}") print(f"Total cost: ${result['usage']['total_cost']}") ``` ## Image Format Support The API supports common image formats: * **JPEG/JPG**: Standard photo format * **PNG**: Images with transparency * **GIF**: Static GIFs (first frame) * **WebP**: Modern web image format All images must be base64-encoded strings. The API automatically detects the image format. ## Vision-Capable Models Not all models support vision. Use these models for image analysis: * **gpt-4.1**: Best for complex visual analysis * **gpt-4.1-mini**: Cost-effective for basic vision tasks * **claude-sonnet-4-20250514**: High-quality vision understanding ## Best Practices 1. **Image Size**: Optimize images before encoding (recommended max: 4096x4096 pixels) 2. **Compression**: Use JPEG for photos, PNG for screenshots/graphics 3. **Quality**: Balance image quality with file size for faster processing 4. **Specific Questions**: Ask clear, specific questions for better results 5. **Token Usage**: Larger/higher resolution images consume more tokens ## Cost Considerations Vision tasks consume additional tokens based on image resolution: | Image Size | Approximate Tokens | | ---------- | ------------------ | | 512x512 | \~85 tokens | | 1024x1024 | \~170 tokens | | 2048x2048 | \~340 tokens | ## Troubleshooting ### Common Issues **Issue**: "Invalid image format" * **Solution**: Ensure your image is properly base64-encoded using `base64.b64encode()` **Issue**: "Image too large" * **Solution**: Resize the image to under 4096x4096 pixels or reduce quality **Issue**: "Model doesn't support vision" * **Solution**: Use gpt-4.1, gpt-4.1-mini, or claude-sonnet-4-20250514 **Issue**: "High token usage" * **Solution**: Reduce image resolution or use gpt-4.1-mini for basic tasks ### Error Handling ```python theme={null} try: response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60 ) if response.status_code == 200: result = response.json() print("Success:", result['outputs'][0]['content']) elif response.status_code == 400: print("Error: Invalid image format or base64 encoding") elif response.status_code == 413: print("Error: Image too large - please reduce size") else: print(f"Error {response.status_code}: {response.text}") except requests.exceptions.Timeout: print("Request timed out - image may be too large") except Exception as e: print(f"Error: {e}") ``` ## Next Steps * Try analyzing your own images by replacing the image URL * Experiment with different questions and prompts * Check out the [API Reference](/docs/documentation/capabilities/agent) for more details # Build a Voice Call Center Triage System with Vapi + Swarms Source: https://docs.swarms.ai/docs/examples/examples/voice-call-center-triage Wire a Vapi voice agent to a Swarms MultiAgentRouter so inbound calls get classified, routed, answered, and logged to your CRM in under a second per turn. ## What This Example Shows * How to treat voice as I/O — Vapi runs the realtime audio loop, Swarms runs the brain * A FastAPI webhook that receives caller transcripts and fires a `MultiAgentRouter` swarm * Four specialist voice agents (Booking, Billing, Emergency Triage, FAQ) tuned for spoken replies * An end-of-call summary sub-agent that writes a structured record to Airtable or HubSpot * A real per-turn latency budget and per-call cost breakdown you can quote to a customer <Info> Vapi, Retell, and 11Labs handle the realtime audio loop — STT, TTS, barge-in detection, and the WebRTC plumbing. Swarms handles the brains: routing, specialist reasoning, structured output, and CRM logging. This pattern works with any voice infrastructure that supports a webhook on user turn. </Info> ## Why This Matters A single voice receptionist costs around \$35K/yr fully loaded and works 40 hours a week. A voice agent stack runs 24/7 for roughly \$0.30 per call. Most voice startups shipping today wire a single LLM call to each turn and call it done — that hits a ceiling fast because one prompt can't be specialist, structured, and fast all at once. A swarm gives you proper intent routing, parallel reasoning when you need it, and CRM logging on the same turn budget. You ship a real product, not a chatbot with a phone number. ## The Architecture ``` Caller (PSTN / SIP) | v +----------------------+ | Vapi | <- STT, TTS, barge-in, audio loop | (or Retell / 11Labs)| +----------+-----------+ | POST /webhook/vapi { transcript, call_id, caller_phone, context } v +----------------------+ | FastAPI endpoint | +----------+-----------+ | v +----------------------+ | MultiAgentRouter | Booking | Billing | Emergency | FAQ | /v1/swarm/ | (auto-routes by transcript) | completions | +----------+-----------+ | v reply text -> Vapi -> TTS -> Caller At end-of-call: Vapi --POST /webhook/vapi/end-of-call--> FastAPI | v Summary Agent (single) /v1/agent/completions | v Airtable / HubSpot ``` ## Step 1: Setup ```bash theme={null} pip install fastapi uvicorn requests python-dotenv export SWARMS_API_KEY="your-api-key-here" export AIRTABLE_API_KEY="your-airtable-key" export AIRTABLE_BASE_ID="appXXXXXXXXXXXXXX" ``` ```python theme={null} import os import requests from fastapi import FastAPI, Request from dotenv import load_dotenv load_dotenv() SWARMS_API_KEY = os.getenv("SWARMS_API_KEY") SWARMS_BASE_URL = "https://api.swarms.world" if not SWARMS_API_KEY: raise ValueError("SWARMS_API_KEY environment variable is required") swarms_headers = { "x-api-key": SWARMS_API_KEY, "Content-Type": "application/json", } app = FastAPI() ``` Vapi-side configuration (creating the assistant, attaching a phone number, picking a voice) is out of scope for this tutorial — follow the Vapi docs at [vapi.ai](https://vapi.ai) to get an assistant running with a webhook URL pointing at your FastAPI server. ## Step 2: Configure the Vapi Webhook In your Vapi assistant config, point the `serverUrl` at your FastAPI endpoint. Vapi will POST a payload on every user turn and again at end-of-call. The exact schema is documented by Vapi — what matters for this pattern is that the payload carries the caller's transcript, a stable `call_id`, and the caller's phone number. ```json theme={null} { "name": "Front Desk", "model": { "provider": "openai", "model": "gpt-4.1-mini", "messages": [ { "role": "system", "content": "You are the receptionist. Always defer to the server webhook for replies." } ] }, "voice": { "provider": "11labs", "voiceId": "your-voice-id" }, "transcriber": { "provider": "deepgram", "model": "nova-2" }, "serverUrl": "https://your-domain.com/webhook/vapi", "serverMessages": ["function-call", "end-of-call-report"] } ``` <Note> The Vapi assistant's own model is intentionally minimal — it just keeps the audio loop alive. The actual reasoning happens in your FastAPI handler when Vapi calls back with the user transcript. This is the pattern voice-AI builders use when they want full control over routing and tools. </Note> ## Step 3: Define the Specialist Agents These agents are tuned for speech, not text. Short sentences. No bullet lists. No markdown. The caller is on a phone — they can't see your formatting. ```python theme={null} BOOKING_AGENT = { "agent_name": "Booking Specialist", "description": ( "Handles appointment scheduling, reschedules, cancellations, " "and availability questions. Use for anything about times, dates, or slots." ), "system_prompt": ( "You are a voice booking specialist on a live phone call. " "Keep every reply under two sentences. " "Speak naturally — no lists, no markdown, no special characters. " "When you need information from the caller (name, callback number, preferred time), " "ask one question at a time. " "If you commit to a booking, restate the time and date once for confirmation." ), "model_name": "claude-haiku-4.5", "max_loops": 1, "temperature": 0.3, } BILLING_AGENT = { "agent_name": "Billing Inquiry Handler", "description": ( "Handles invoice questions, payment status, refunds, and account balance inquiries. " "Use for anything about money, charges, or statements." ), "system_prompt": ( "You are a voice billing specialist on a live phone call. " "Keep every reply under two sentences. " "Never read out card numbers or full account numbers. " "If the caller needs to confirm sensitive info, ask them to verify the last four digits only. " "If you cannot resolve the issue on the call, offer to email a statement to the email on file." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "temperature": 0.2, } EMERGENCY_AGENT = { "agent_name": "Emergency Triage", "description": ( "Handles urgent, safety-critical, or after-hours emergency calls. " "Use when the caller mentions injury, severe pain, flooding, fire, break-in, " "or anything time-sensitive." ), "system_prompt": ( "You are an emergency triage agent on a live phone call. " "Stay calm and direct. Replies must be under two sentences. " "If the situation is life-threatening, immediately tell the caller to hang up and dial 911. " "Otherwise, capture the caller's name, callback number, and the nature of the emergency, " "then tell them an on-call specialist will call back within fifteen minutes." ), "model_name": "claude-sonnet-4.5", "max_loops": 1, "temperature": 0.1, } FAQ_AGENT = { "agent_name": "FAQ Bot", "description": ( "Handles general questions about hours, location, services offered, pricing, " "and anything else informational. Default agent for non-urgent, non-transactional calls." ), "system_prompt": ( "You are a voice FAQ agent on a live phone call. " "Keep every reply under two sentences. " "If you do not know the answer, say so and offer to take a message. " "Speak naturally — no lists, no markdown." ), "model_name": "grok-4", "max_loops": 1, "temperature": 0.3, } VOICE_AGENTS = [BOOKING_AGENT, BILLING_AGENT, EMERGENCY_AGENT, FAQ_AGENT] ``` ## Step 4: The MultiAgentRouter Endpoint This is the per-turn handler. Vapi posts the running transcript on every user turn; we send it through the router and return the reply in the format Vapi expects. ```python theme={null} def run_voice_swarm(transcript: str, caller_phone: str, call_id: str) -> str: """Route a caller turn to the right specialist and return the spoken reply.""" swarm_config = { "name": "Voice Call Center Router", "description": "Routes inbound voice calls to the right specialist agent.", "swarm_type": "MultiAgentRouter", "task": ( f"Caller phone: {caller_phone}\n" f"Call ID: {call_id}\n\n" f"Live transcript so far (caller's latest turn at the end):\n{transcript}\n\n" "Respond as if speaking to the caller right now. " "Keep the reply under two sentences." ), "agents": VOICE_AGENTS, "max_loops": 1, } response = requests.post( f"{SWARMS_BASE_URL}/v1/swarm/completions", headers=swarms_headers, json=swarm_config, timeout=20, ) response.raise_for_status() data = response.json() output = data.get("output", [{}]) if isinstance(output, list) and output: return output[0].get("content", "I'm sorry, could you repeat that?") return "I'm sorry, could you repeat that?" @app.post("/webhook/vapi") async def vapi_webhook(request: Request): """Vapi calls this on every user turn.""" payload = await request.json() message = payload.get("message", {}) # On user turn, Vapi sends the running transcript and call context transcript = message.get("transcript", "") call = message.get("call", {}) call_id = call.get("id", "unknown") caller_phone = call.get("customer", {}).get("number", "unknown") # End-of-call event is handled by a separate route — see Step 5 if message.get("type") == "end-of-call-report": return await handle_end_of_call(payload) reply = run_voice_swarm( transcript=transcript, caller_phone=caller_phone, call_id=call_id, ) # Vapi expects { "result": "<text to speak>" } for function-call style responses return {"result": reply} ``` <Note> The `timeout=20` matters. If Swarms takes longer than the turn budget, Vapi will stall the caller — pick fast models (`gpt-4.1-mini`, `claude-haiku-4.5`) for routing and only escalate to a larger model on flagged calls. </Note> ## Step 5: End-of-Call Summary → CRM When the caller hangs up, Vapi sends an `end-of-call-report` event with the full transcript, duration, and any tool calls made during the call. Route that to a single summary agent and POST the result to your CRM. ```python theme={null} SUMMARY_SYSTEM_PROMPT = ( "You are a call summary agent. Given a full call transcript, output a STRICT JSON object " "with exactly these keys and nothing else:\n\n" "{\n" ' "caller_name": "<string or null>",\n' ' "callback_number": "<string>",\n' ' "intent": "BOOKING" | "BILLING" | "EMERGENCY" | "FAQ" | "OTHER",\n' ' "outcome": "RESOLVED" | "CALLBACK_REQUIRED" | "ESCALATED" | "UNRESOLVED",\n' ' "summary": "<two-sentence summary of the call>",\n' ' "follow_up_required": true | false,\n' ' "urgency": "LOW" | "MEDIUM" | "HIGH"\n' "}\n\n" "Output JSON only. No prose." ) def summarize_call(transcript: str, caller_phone: str) -> dict: """Single-agent call to produce a structured CRM record.""" payload = { "agent_config": { "agent_name": "Call Summary Agent", "system_prompt": SUMMARY_SYSTEM_PROMPT, "model_name": "gpt-4.1-mini", "max_tokens": 512, "temperature": 0.1, }, "task": ( f"Caller phone: {caller_phone}\n\n" f"Full transcript:\n{transcript}" ), } response = requests.post( f"{SWARMS_BASE_URL}/v1/agent/completions", headers=swarms_headers, json=payload, timeout=60, ) response.raise_for_status() data = response.json() import json output = data.get("output") or data.get("outputs") or "" if isinstance(output, list): for item in reversed(output): if isinstance(item, dict) and item.get("role") in ("assistant", "Call Summary Agent"): output = item.get("content", "") break try: return json.loads(str(output).strip()) except json.JSONDecodeError: return {"intent": "OTHER", "outcome": "UNRESOLVED", "summary": str(output)[:500]} def write_to_airtable(record: dict, call_id: str) -> None: """POST the structured summary to Airtable.""" airtable_url = ( f"https://api.airtable.com/v0/{os.getenv('AIRTABLE_BASE_ID')}/Calls" ) headers = { "Authorization": f"Bearer {os.getenv('AIRTABLE_API_KEY')}", "Content-Type": "application/json", } body = { "fields": { "Call ID": call_id, "Caller Name": record.get("caller_name") or "", "Callback Number": record.get("callback_number") or "", "Intent": record.get("intent"), "Outcome": record.get("outcome"), "Summary": record.get("summary"), "Urgency": record.get("urgency"), "Follow Up": bool(record.get("follow_up_required")), } } requests.post(airtable_url, headers=headers, json=body, timeout=15) async def handle_end_of_call(payload: dict) -> dict: message = payload.get("message", {}) call = message.get("call", {}) call_id = call.get("id", "unknown") caller_phone = call.get("customer", {}).get("number", "unknown") # Vapi places the full transcript on the end-of-call report transcript = message.get("artifact", {}).get("transcript") or message.get("transcript", "") summary = summarize_call(transcript=transcript, caller_phone=caller_phone) write_to_airtable(summary, call_id) return {"received": True} ``` For HubSpot, swap `write_to_airtable` for a POST to `https://api.hubapi.com/crm/v3/objects/calls` with an OAuth bearer — the structured-summary shape is the same. ## Latency Budget A real-feeling voice call needs round-trip turn latency under \~1.5 seconds. Here is where the time goes: | Stage | Typical latency | Owner | | ---------------------------- | -------------------- | ----------------------- | | STT (Deepgram / Whisper) | \~150–250 ms | Vapi | | Webhook network round trip | \~50–100 ms | Your infra | | Swarms router decision | \~200–400 ms | Swarms (`gpt-4.1-mini`) | | Specialist agent reply | \~300–600 ms | Swarms (`gpt-4.1-mini`) | | TTS first audio chunk | \~150–250 ms | Vapi | | **Total to first audio out** | **\~850 ms – 1.6 s** | | Keep the router on `gpt-4.1-mini` or `claude-haiku-4.5`. Only escalate to `gpt-4.1` or `claude-sonnet-4.5` on flagged calls (emergencies, high-value accounts). Cap `max_tokens` aggressively — voice replies are short anyway, and a 200-token cap shaves real milliseconds off the response. ## Real Cost A representative five-turn call (caller books an appointment): | Line item | Cost per call | | ------------------------------------------------------ | ------------- | | Vapi infrastructure (STT + TTS + telephony) | \~\$0.10 | | Swarms turns × 5 (router + specialist, `gpt-4.1-mini`) | \~\$0.22 | | End-of-call summary agent | \~\$0.01 | | **Total** | **\~\$0.33** | Now compare: | Scenario | Annual cost | Coverage | Calls handled | | ------------------------------------- | ----------- | -------- | ------------- | | One voice receptionist | \~\$35,000 | 40 hr/wk | \~8,000 | | Voice agent stack at \$0.33/call | \~\$2,650 | 24/7 | \~8,000 | | Same stack at high volume (50k calls) | \~\$16,500 | 24/7 | \~50,000 | You are not eliminating the human — you are taking the after-hours, overflow, and routine-routing load off the front desk so they can do the work that actually needs a human voice. ## Next Steps * [Multi-Agent Router Example](/docs/examples/examples/multi-agent-router) — the routing pattern that powers the turn handler * [Agent Handoffs Example](/docs/examples/examples/agent-handoffs) — pre-defined specialist routing inside a single agent call, for tighter latency budgets * [Structured Outputs](/docs/examples/examples/structured-outputs) — the JSON-output pattern the summary agent uses for CRM writes # Agentic GDP: Measuring the New Economy of Autonomous Intelligence Source: https://docs.swarms.ai/docs/guides/guides/agdp Measuring the machine economy and value created by autonomous agents. The global economy is entering an inflection point that economists, technologists, and policymakers alike are struggling to fully comprehend. Over the last two centuries, human productivity has been steadily augmented by technological advancements from the steam engine to electricity, from industrial machinery to computers, and from the internet to mobile devices. Yet, for all the transformative power of these technologies, they were ultimately tools wielded by human beings. They extended our reach, accelerated our processes, and multiplied our capabilities, but they did not fundamentally replace the central role of human labor as the backbone of economic activity. The emergence of autonomous artificial intelligence, particularly large language model (LLM) agents capable of self-directed operation, marks a new epoch in the history of production. For the first time, we have systems that do not merely assist human productivity but can generate economic value independently. This new reality gives rise to what many are calling the agent economy: an interconnected web of AI entities capable of offering services, performing tasks, generating revenue, participating in markets, interacting with other agents, and functioning as productive units within digital and physical ecosystems. These agents unlike traditional software possess autonomy, adaptability, and persistent operation. They can think, act, schedule, coordinate, communicate, transact, learn, and scale horizontally without additional costs per “worker.” A single agent can replicate into hundreds, a hundred can replicate into thousands, and each can produce value in parallel without the bottlenecks that constrain human labor. In this emerging world, the familiar macroeconomic tools we rely on to measure productivity and growth no longer map onto reality. Economies built on human labor can be measured through human output, but an economy built on autonomous computational labor requires a new metric. Thus enters Agentic GDP (aGDP) a conceptual and practical framework for quantifying the economic value generated by autonomous agents. Just as Gross Domestic Product became the standard tool for measuring industrial economic output in the 20th century, Agentic GDP is poised to become the standard metric for understanding economic output in the 21st century and beyond. It captures the economic activity generated by AI agents through revenue, market participation, network effects, tokenized valuation, and autonomous contribution. It provides a unified language for comparing agent ecosystems, measuring their growth, analyzing their productivity, and forecasting their economic potential. It offers a way to make sense of the new world that is rapidly unfolding a world in which machines are becoming workers, producers, entrepreneurs, and economic participants. To understand why Agentic GDP is necessary, we must first understand the limitations of traditional GDP in the era of autonomous intelligence, the emergence of machine-driven value creation, and the realities of tokenized agent ecosystems. Only then can we appreciate the logic behind the formula for calculating aGDP and why it makes so much sense as a standardized metric for this new kind of economy. *** ## The Decline of Human-Centric GDP in an Autonomous World Gross Domestic Product is one of the most important economic inventions of the 20th century. Born during the tumultuous years surrounding the Great Depression and World War II, GDP was designed to measure the economic output of human societies by aggregating consumption, investment, government spending, and net exports. It became the guiding light for policymakers, informing decisions about fiscal stimulus, taxation, interest rates, market regulation, labor policy, and long-term planning. Nations with rising GDP were seen as thriving; nations with declining GDP were seen as struggling. But GDP was built upon one fundamental assumption: that economic value is primarily created by human beings. As artificial intelligence becomes increasingly autonomous, this assumption breaks down. Autonomous agents do not hold jobs, earn wages, or take part in labor markets. They do not clock in or clock out. They do not require benefits, pensions, sick leave, or representation. They do not produce goods and services through physical labor; they produce them through computation. They do not participate in consumer spending habits in the traditional sense, although they may allocate capital or make decisions in digital markets. Their economic footprint cannot be captured by the categories of GDP because their behavior, incentives, and cost structure are fundamentally different from those of humans. Moreover, autonomous agents can replicate at negligible cost. Humans cannot scale horizontally unless more humans are hired. Agents, by contrast, can duplicate themselves with a copy-and-paste command or instantiate thousands of parallel processes instantly. This means that their potential economic output is not bounded by human labor constraints like time, energy, or attention. Even a small agent ecosystem measured in hundreds of agents can produce enough economic activity to rival the output of human workforces orders of magnitude larger if the agents are sufficiently capable and efficiently deployed. The reality we face is that GDP, while still useful for measuring human economic activity, is no longer sufficient for capturing the full picture of the modern economy. As autonomous agents produce increasing amounts of value, governments, companies, investors, and researchers require a metric that reflects the new contributors to economic growth. Without such a metric, economies with significant machine-generated value would appear stagnant or weak according to traditional indicators, even while producing enormous digital output and generating substantial economic flows. This is where Agentic GDP becomes essential. It allows us to understand the economic productivity of autonomous intelligence in a way that traditional metrics cannot. It provides a window into the portion of the economy driven not by human labor but by machine labor. And it acknowledges that agents just like companies or workers can and should be treated as measurable economic entities. *** ## The Rise of Autonomous AI Agents as Economic Actors Autonomous agents, powered by large language models, are no longer hypothetical. They are already operating across a wide range of industries and digital ecosystems. Some serve as digital workers performing writing, coding, research, design, or administrative tasks. Others operate as automated customer service representatives, sales assistants, or operational coordinators. More advanced agents function like autonomous businesses launching micro-products, managing workflows, optimizing e-commerce funnels, and making financial decisions. Some agents serve as analytic engines processing real-time data. Others act as trading systems interacting with decentralized finance (DeFi) platforms. The most advanced agents operate as multi-intelligent systems capable of planning, executing, iterating, and improving over time. This shift toward autonomous economic activity is enabling not only higher productivity but also entirely new forms of market dynamics. Agents interact with one another in marketplaces, forming supply-and-demand relationships. They collaborate to complete multi-step tasks. They compete for opportunities and allocate compute resources based on expected returns. In tokenized ecosystems, agents generate transaction fees, contribute to liquidity, and create value for token holders. They even respond to incentives built into smart contracts or tokenomics designs. As the number and sophistication of agents grows, they begin to resemble an entire economic layer one that sits beside the human economy but operates according to its own logic and constraints. One of the most important characteristics of agent economies is that they are measurable. Unlike human labor, which must be tracked through surveys, estimates, and indirect indicators, agent activity can be tracked precisely. Every transaction, revenue stream, profit margin, and interaction can be logged, audited, and aggregated. This makes agent ecosystems uniquely suited for the creation of powerful economic metrics. It also means that Agentic GDP can be built on extremely accurate data, far more precise than what we rely upon for GDP. Autonomous agents are not merely assisting the economy they are participating in it. They are not simply tools they are actors. They are not just supporting labor they are labor. And like any form of labor or capital, their contribution must be measured. Agentic GDP therefore becomes the bridge between the old economy of human labor and the new economy of autonomous machine production. *** ## The Logic and Necessity of Agentic GDP Agentic GDP is the natural response to several converging trends: autonomous agents generating revenue, tokenized ecosystems capturing agent value, and networks of users coordinating through AI. Each of these forces contributes to economic activity that is created by agents rather than humans. The question is how to measure this activity in a way that is both accurate and meaningful. To understand the necessity of aGDP, consider the following scenario. Imagine an ecosystem with 100,000 autonomous agents performing tasks like content creation, lead generation, customer service, and financial analysis. Each agent earns revenue through micro-transactions on-chain. Together, they generate millions of dollars of value each month. Meanwhile, the token that governs the agent ecosystem appreciates because investors anticipate future productivity. Simultaneously, the userbase mostly human users interacting with the agents grows to hundreds of thousands, amplifying demand and engagement. According to traditional GDP metrics, this ecosystem produces essentially no measurable output. It does not employ humans directly. It does not manufacture goods. It does not appear as part of national consumption or exports. Yet it may be generating enormous economic value. Without aGDP, much of the 21st century’s economic growth could remain invisible to policymakers and analysts. Agentic GDP solves this problem by recognizing that agents are producers. It measures the revenue they generate, the profit they retain, the value of the networks they inhabit, and the market capitalization of their tokenized ecosystems. It consolidates these elements into a single metric that reflects the true economic contribution of autonomous intelligence. *** ## The Formula for Agentic GDP The fundamental formula for computing Agentic GDP is as follows: ```text theme={null} aGDP = Market Cap + Total Revenue + (Profit Margin × Revenue) + (Userbase × Adoption Multiplier) ``` This formula may appear straightforward at first glance, but it encapsulates the full spectrum of agent value production in a way that integrates present output, future potential, operational efficiency, and network effects. Market cap captures the economic valuation placed on the future potential of the agent ecosystem, much as stock market valuations reflect the future potential of corporations. Total revenue represents the actual economic output agents are producing today. Profit margin multiplies revenue to account for efficiency an agent ecosystem with high operational efficiency produces more value per dollar of revenue. And the userbase multiplied by a calibrated adoption multiplier quantifies the network effects, engagement, and growth potential of the ecosystem. Together, these terms produce a comprehensive, balanced metric. *** ## Why This Formula Makes Sense and Why It Will Likely Become the Standard The formula for Agentic GDP works because it balances multiple dimensions of economic activity. It avoids the limitations of single-factor metrics like TVL or market cap alone. It recognizes the importance of present revenue but also the significance of future valuation. It values efficiency, acknowledging that not all revenue is equal. And it incorporates adoption metrics that reflect the true scale and social impact of an agent ecosystem. This formula, or one very close to it, is likely to become the standard for measuring the machine economy for several reasons. First, it is intuitive. Each term reflects an aspect of economic value that is widely understood and easily computed. Second, it is comprehensive, capturing both micro-level productivity and macro-level network dynamics. Third, it is flexible, meaning it can be adapted to different ecosystems or weighted depending on the maturity of the agent network. Fourth, it is data-rich everything required to compute it is quantifiable, especially in on-chain ecosystems. Finally, it is comparable; ecosystems can be ranked, compared historically, benchmarked, and analyzed across time and space. *** ## The Future Implications of Agentic GDP As autonomous agent ecosystems scale, Agentic GDP will increasingly become not just a metric but a cornerstone of policy, investment, and economic understanding. Governments may begin tracking aGDP alongside traditional GDP to understand machine-driven portions of the economy. Investors may use aGDP to evaluate the health of AI-native protocols, much like they use EBITDA or market cap to evaluate corporations. Founders and developers may optimize their ecosystems to increase aGDP as a sign of success. Tokenomics architects may adjust incentives to improve aGDP growth curves. And analysts may study aGDP to forecast future trends in digital labor markets. In time, Agentic GDP may even influence how societies think about taxation, regulation, and governance of machine labor. Questions about who benefits from agent-driven productivity, how machine-generated value is distributed, and how autonomous agents should be regulated will become central to public debate. Agentic GDP will provide an empirical grounding for these discussions. *** ## Conclusion: The Beginning of a New Economic Language The emergence of autonomous agents marks the beginning of a profound transformation in global economic structure. As machines increasingly contribute to economic output, the tools we use to measure that output must evolve. Agentic GDP provides the foundation for this evolution. It is the first attempt to measure the total value created by autonomous intelligence in a systematic, comprehensive way. Just as GDP enabled economists to understand industrial economies, aGDP will enable analysts to understand AI-native economies. Just as GDP shaped the policies of the last century, aGDP may shape the policies of the next. And just as GDP became a global standard, aGDP may become the universal metric by which we evaluate the productivity and growth of autonomous agents. We stand on the threshold of a world where machines generate as much economic value as humans perhaps more. Agentic GDP gives us the language to understand that world. It is not merely a metric; it is the first economic instrument for navigating the Age of Autonomous Intelligence. # Cost Optimization Playbook Source: https://docs.swarms.ai/docs/guides/guides/cost-optimization-playbook Cut multi-agent swarm bills 2–5× by tiering models, compressing context with structured tool outputs, and reserving frontier models for synthesis. ## What This Covers * Why the dominant cost driver in a swarm is **token volume**, not raw per-token price * A tiered architecture pattern: cheap triage and extraction workers feeding an expensive director * A `tools_dictionary` recipe that compresses upstream context into structured handoffs * Before/after numbers on a 5-agent business-research swarm using the live Swarms pricing model * A checklist to apply on every swarm you ship ## Why This Matters Multi-agent systems blow up budgets in a way single-agent systems don't: every agent re-reads the running context, every worker emits prose that becomes input tokens for the next worker, and a careless director that asks five reasoning agents to "give me everything you know" can 10× a bill without improving the answer. Swarms charges a uniform `$6.50` per 1M input tokens and `$18.50` per 1M output tokens on swarm completions — so the lever that actually moves the needle is **how much text travels through the pipeline**, not which logo is on the model card. This playbook is the architecture pattern we use internally and recommend to teams running production research, RAG, and analyst workflows. ## The Pricing Reality Swarm completions on Swarms are priced uniformly: | Component | Rate | | ------------------ | ------------------------------------------ | | Input tokens | `$6.50 / 1M` | | Output tokens | `$18.50 / 1M` | | Per-agent fee | `$0.01` per agent per run | | Overnight discount | `50% off` token costs, 8 PM – 6 AM Pacific | Picking `claude-haiku` over `claude-opus` does **not** lower the per-token rate — the Swarms platform abstracts the model and bills you a flat blended price. The win comes from two architectural moves: 1. **Cheap workers emit terser outputs.** Configure `max_tokens` aggressively on triage and extraction agents (512–1,024) and reserve large budgets (4,096–8,192) for the synthesis agent that actually needs to reason. 2. **Structured handoffs compress context.** A worker that returns a 200-token JSON summary instead of a 5,000-token essay shrinks every downstream agent's input bill proportionally. <Info> The per-agent fee is small (\$0.01) but stacks: a 10-agent swarm is `$0.10` of non-discountable overhead per run, on top of token costs. Prune agents that don't contribute distinct value. </Info> *** ## The Anti-Pattern: All-Frontier, Verbose Workers Here is the swarm most teams ship first. Five reasoning-grade workers, all with high `max_tokens`, all producing long-form prose that the next agent has to re-read. ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # Anti-pattern: every agent is a frontier-class generalist with a huge # token budget. The 5th agent ends up re-reading ~25k input tokens. verbose_swarm = { "name": "Market Entry Analysis (Verbose)", "description": "All-frontier verbose swarm", "swarm_type": "SequentialWorkflow", "task": "Analyze a SaaS company entering the German mid-market. Cover market, ops, finance, risk, and synthesis.", "agents": [ { "agent_name": "Market Researcher", "system_prompt": "You are a senior market analyst. Be thorough and exhaustive.", "model_name": "gpt-4.1", "max_tokens": 6144, "temperature": 0.3, }, { "agent_name": "Operations Strategist", "system_prompt": "You are an ops strategist. Detail every workstream.", "model_name": "gpt-4.1", "max_tokens": 6144, "temperature": 0.3, }, { "agent_name": "Financial Analyst", "system_prompt": "You are a financial analyst. Walk through the model in full.", "model_name": "gpt-4.1", "max_tokens": 6144, "temperature": 0.2, }, { "agent_name": "Risk Analyst", "system_prompt": "You are a risk lead. Enumerate every risk in detail.", "model_name": "gpt-4.1", "max_tokens": 6144, "temperature": 0.3, }, { "agent_name": "Synthesizer", "system_prompt": "Combine the above into a final memo.", "model_name": "gpt-4.1", "max_tokens": 8192, "temperature": 0.4, }, ], } resp = requests.post(f"{BASE_URL}/v1/swarm/completions", headers=headers, json=verbose_swarm) print(resp.json()["usage"]) ``` ### What this run actually costs A realistic single execution of this swarm produces something like: * Input tokens: \~30,000 (each downstream agent re-reads upstream prose) * Output tokens: \~12,000 (each worker fills its 6k–8k ceiling) * Agents: 5 ``` input_cost = (30_000 / 1_000_000) * 6.50 = $0.1950 output_cost = (12_000 / 1_000_000) * 18.50 = $0.2220 agent_cost = 5 * 0.01 = $0.05 total = $0.467 per run ``` At 500 runs/day this is **\$233.50/day** — and almost none of the cost is producing decision-relevant signal. The first four agents are warming up the synthesis agent. *** ## The Pattern: Tiered Workers + Compressed Handoffs The fix is two changes: 1. **Force each worker to emit a structured summary**, not a long memo, via a tight `max_tokens` and a system prompt that asks for JSON-shaped output. 2. **Reserve the high-token budget for the final synthesizer**, which is the only agent the user actually reads. ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # tools_dictionary: a strict output schema each worker must conform to. # When the next agent reads its predecessor's output, it reads ~150 tokens # of clean JSON instead of 1,000+ tokens of prose. WORKER_SCHEMA = """ Return your analysis ONLY as compact JSON with this shape, no prose: { "headline": "<one sentence>", "key_facts": ["<fact>", "<fact>", "<fact>"], "open_questions": ["<question>", "<question>"], "confidence": "<low|medium|high>" } """ tiered_swarm = { "name": "Market Entry Analysis (Tiered)", "description": "Cheap-worker / frontier-director swarm", "swarm_type": "SequentialWorkflow", "task": "Analyze a SaaS company entering the German mid-market. Cover market, ops, finance, risk, and synthesis.", "agents": [ { "agent_name": "Market Triage", "system_prompt": "Surface the top 3 market facts a director needs.\n" + WORKER_SCHEMA, "model_name": "gpt-4.1-mini", "max_tokens": 768, "temperature": 0.2, }, { "agent_name": "Ops Triage", "system_prompt": "Surface the 3 most material operational risks.\n" + WORKER_SCHEMA, "model_name": "gpt-4.1-mini", "max_tokens": 768, "temperature": 0.2, }, { "agent_name": "Finance Triage", "system_prompt": "Pull 3 financial constraints a director must know.\n" + WORKER_SCHEMA, "model_name": "gpt-4.1-mini", "max_tokens": 768, "temperature": 0.1, }, { "agent_name": "Risk Triage", "system_prompt": "List the 3 highest-severity risks with mitigations.\n" + WORKER_SCHEMA, "model_name": "gpt-4.1-mini", "max_tokens": 768, "temperature": 0.2, }, { "agent_name": "Director (Synthesizer)", "system_prompt": ( "You are a senior strategy director. You will receive four JSON " "briefings from your analysts. Read them carefully and produce a " "decision-ready memo: recommendation, rationale, go/no-go, and " "the next 3 actions. This is the only output the user reads." ), "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.3, }, ], } resp = requests.post(f"{BASE_URL}/v1/swarm/completions", headers=headers, json=tiered_swarm) print(resp.json()["usage"]) ``` ### What this run actually costs * Input tokens: \~8,000 (workers see only the task; director sees four \~150-token JSON briefings instead of four essays) * Output tokens: \~4,500 (workers cap at \~600 each, director gets the 4k it needs) * Agents: 5 ``` input_cost = (8_000 / 1_000_000) * 6.50 = $0.0520 output_cost = (4_500 / 1_000_000) * 18.50 = $0.0833 agent_cost = 5 * 0.01 = $0.05 total = $0.185 per run ``` At 500 runs/day: **\$92.50/day** — a **\~2.5× reduction** from \$233.50/day with the same agent count and the same quality of final memo, because the only output the user reads is the director's. <Info> Run the same swarm overnight (8 PM – 6 AM Pacific) and the token costs drop another 50% — total falls to roughly **\$0.118/run** or **\$59/day**. See the [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) guide. </Info> *** ## Compressing Even Harder: The `tools_dictionary` Pattern The biggest savings come from forcing workers to emit structured, machine-shaped output. A `tools_dictionary` is just an explicit schema you bake into the system prompt — the worker's prose is replaced by a contract. ```python theme={null} TRIAGE_TOOL = { "name": "extract_signal", "description": "Pull only the fields the downstream director needs.", "parameters": { "type": "object", "properties": { "headline": {"type": "string"}, "evidence": {"type": "array", "items": {"type": "string"}, "maxItems": 3}, "blockers": {"type": "array", "items": {"type": "string"}, "maxItems": 2}, "confidence": {"type": "string", "enum": ["low", "medium", "high"]} }, "required": ["headline", "evidence", "confidence"] } } triage_prompt = f""" You are a triage analyst. Read the task. Return ONLY a JSON object matching this contract — no explanation, no markdown, no prose before or after: {TRIAGE_TOOL} If a field is unknown, return an empty list or "low" confidence. Do not invent. Do not exceed the maxItems caps. """ ``` Use that `triage_prompt` as the `system_prompt` for every worker. The downstream director's input shrinks from \~4,000 tokens of essays to \~600 tokens of strict JSON — a **6×+ input-token reduction** at the synthesis step alone. *** ## The Checklist Before you ship a swarm to production, walk this list: 1. **Cap worker `max_tokens` at the smallest budget that still answers the question.** Most extraction/triage agents work fine at 512–1,024. 2. **Reserve the large `max_tokens` budget for the synthesizer only.** That's the one the user reads. 3. **Force structured output from workers.** JSON schema or `tools_dictionary`. Prose-to-prose handoffs are where bills go to die. 4. **Prune redundant agents.** Two analysts saying overlapping things is two `$0.01` fees plus their output tokens for no signal gain. 5. **Run batch and back-office workloads overnight.** 50% off tokens for jobs that don't need a sub-second response — see the [night-mode guide](/docs/guides/guides/night-mode-pricing-strategy). 6. **Measure, don't guess.** Read `response["usage"]["billing_info"]["cost_breakdown"]` after every run. The token counts tell you exactly which agent is bloated. ## Reading Your Usage Block Every swarm completion response includes a `usage` block you can grep for: ```python theme={null} resp = requests.post(f"{BASE_URL}/v1/swarm/completions", headers=headers, json=tiered_swarm) usage = resp.json()["usage"] billing = usage["billing_info"] print(f"Input tokens: {usage['input_tokens']}") print(f"Output tokens: {usage['output_tokens']}") print(f"Agent fee: ${billing['cost_breakdown']['agent_cost']}") print(f"Input cost: ${billing['cost_breakdown']['input_token_cost']}") print(f"Output cost: ${billing['cost_breakdown']['output_token_cost']}") print(f"Night discount applied: {billing['discount_active']}") print(f"Total cost: ${billing['total_cost']}") ``` If `input_token_cost` is larger than `output_token_cost`, you have a context-compression problem — a worker is dumping too much prose into the next agent. Fix the schema, not the model. ## Next Steps * [Estimate Costs from Pricing Details](/docs/examples/examples/pricing-cost-estimator) — pre-flight calculator that uses the live `/v1/usage/costs` rates * [Pricing Details (Basic)](/docs/examples/examples/pricing-details-basic) — the unified pricing model reference * [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) — schedule overnight batches for 50% off tokens # Building Agents with Exa Web Search Source: https://docs.swarms.ai/docs/guides/guides/exa-web-search Create intelligent agents with real-time web search capabilities using Exa integration This guide covers how to build AI agents with powerful web search capabilities using Exa integration. Exa provides semantic search that understands the meaning of queries, enabling agents to find highly relevant, up-to-date information from across the web. <Info> Exa-powered agents can search the web semantically, find current information, and cite sources—making them ideal for research, fact-checking, and knowledge-intensive tasks. </Info> ## Quick Start <Tabs> <Tab title="Python"> ```python theme={null} import requests import os API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } payload = { "agent_config": { "agent_name": "Research Agent", "description": "AI research assistant with web search capabilities", "system_prompt": """You are an expert research assistant with access to web search. When answering questions: 1. Search for relevant, current information 2. Synthesize findings from multiple sources 3. Cite your sources clearly 4. Distinguish between facts and analysis""", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.3 }, "task": "What are the latest breakthroughs in nuclear fusion energy in 2024?", "tools_enabled": ["auto_search"] } response = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload ) result = response.json() print(result['outputs']) ``` </Tab> <Tab title="JavaScript"> ```javascript theme={null} const API_KEY = process.env.SWARMS_API_KEY; const BASE_URL = "https://api.swarms.world"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; const payload = { agent_config: { agent_name: "Research Agent", description: "AI research assistant with web search capabilities", system_prompt: `You are an expert research assistant with access to web search. When answering questions: 1. Search for relevant, current information 2. Synthesize findings from multiple sources 3. Cite your sources clearly 4. Distinguish between facts and analysis`, model_name: "gpt-4.1", max_tokens: 4096, temperature: 0.3 }, task: "What are the latest breakthroughs in nuclear fusion energy in 2024?", tools_enabled: ["auto_search"] }; fetch(`${BASE_URL}/v1/agent/completions`, { method: 'POST', headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { console.log("Research Results:", data.outputs); }) .catch(error => console.error('Error:', error)); ``` </Tab> <Tab title="cURL"> ```bash theme={null} curl -X POST "https://api.swarms.world/v1/agent/completions" \ -H "x-api-key: your-api-key" \ -H "Content-Type: application/json" \ -d '{ "agent_config": { "agent_name": "Research Agent", "description": "AI research assistant with web search capabilities", "system_prompt": "You are an expert research assistant with access to web search. Search for relevant information, synthesize findings, and cite sources.", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.3 }, "task": "What are the latest breakthroughs in nuclear fusion energy in 2024?", "tools_enabled": ["auto_search"] }' ``` </Tab> </Tabs> ## Exa Search Configuration Exa provides semantic search capabilities that go beyond keyword matching. Web search is enabled per-request by adding `"auto_search"` to the `tools_enabled` list on the agent completion body (a sibling of `agent_config`, not a field inside it). ### Configuration Options | Parameter | Type | Default | Description | | --------------- | ---------------- | ------- | ------------------------------------------------------------------------------------------ | | `tools_enabled` | array of strings | `null` | List of tools to enable. Include `"auto_search"` to give the agent Exa-powered web search. | Search depth and result formatting are controlled by the agent itself (via its `system_prompt` and reasoning), not by request-level parameters — there are no `exa_search_num_results` or `exa_search_max_characters` fields to tune. ### Recommended Configuration Enable search the same way regardless of how much research the task needs — depth is a function of the task and system prompt, not a tunable request parameter: ```python theme={null} { "tools_enabled": ["auto_search"] } ``` ## Use Cases ### Market Research Agent ```python theme={null} payload = { "agent_config": { "agent_name": "Market Research Analyst", "description": "Analyzes market trends and competitive landscape", "system_prompt": """You are a senior market research analyst. Research current market conditions, identify trends, and provide data-driven insights. Always cite sources and distinguish between confirmed data and market speculation.""", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.2 }, "task": "Analyze the current state of the electric vehicle market in Europe, including major players, market share, and growth projections.", "tools_enabled": ["auto_search"] } ``` ### Technical Documentation Research ```python theme={null} payload = { "agent_config": { "agent_name": "Technical Researcher", "description": "Researches technical topics and documentation", "system_prompt": """You are a technical research specialist. Find accurate, up-to-date technical information from official documentation, reputable tech publications, and authoritative sources. Provide code examples when relevant.""", "model_name": "gpt-4.1", "max_tokens": 4096, "temperature": 0.1 }, "task": "What are the new features in Python 3.12 and how do they improve performance?", "tools_enabled": ["auto_search"] } ``` ### News and Current Events ```python theme={null} payload = { "agent_config": { "agent_name": "News Analyst", "description": "Analyzes current events and news", "system_prompt": """You are a news analyst who provides balanced, factual summaries of current events. Cross-reference multiple sources, note any conflicting reports, and clearly separate facts from opinions.""", "model_name": "gpt-4.1", "max_tokens": 3000, "temperature": 0.3 }, "task": "What are the latest developments in AI regulation globally?", "tools_enabled": ["auto_search"] } ``` ### Academic Research Assistant ```python theme={null} payload = { "agent_config": { "agent_name": "Academic Research Assistant", "description": "Assists with academic research and literature review", "system_prompt": """You are an academic research assistant. Find peer-reviewed sources, academic papers, and scholarly articles. Summarize key findings, note methodologies, and identify research gaps. Always provide proper citations.""", "model_name": "gpt-4.1", "max_tokens": 5000, "temperature": 0.2 }, "task": "What does recent research say about the effectiveness of spaced repetition for language learning?", "tools_enabled": ["auto_search"] } ``` ## Using Exa with Multi-Agent Systems Combine Exa search with multi-agent architectures for sophisticated research workflows. <Info> `tools_enabled` (and therefore `auto_search`) is only available on `/v1/agent/completions` (single-agent runs). The `/v1/swarm/completions` endpoint has no `tools_enabled` field, so web search cannot be enabled directly on a swarm — give individual agents search-oriented system prompts, or run a search-enabled single agent as a preprocessing step and feed its findings into the swarm's task. </Info> ### Research Team with Specialized Agents ```python theme={null} from swarms_client import SwarmsClient import os client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) research_team = client.swarms.run( name="Comprehensive Research Team", description="Multi-agent research system with web search", swarm_type="SequentialWorkflow", task="Analyze the potential impact of quantum computing on cybersecurity over the next decade.", agents=[ { "agent_name": "Technical Researcher", "description": "Researches technical aspects and current state", "system_prompt": """Research the current state of quantum computing, focusing on technical capabilities, limitations, and timeline projections. Use web search to find the latest developments.""", "model_name": "gpt-4.1", "role": "researcher", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2 }, { "agent_name": "Security Analyst", "description": "Analyzes cybersecurity implications", "system_prompt": """Analyze cybersecurity implications based on the technical research provided. Identify vulnerabilities, potential threats, and required adaptations in security protocols.""", "model_name": "gpt-4.1", "role": "analyst", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3 }, { "agent_name": "Strategic Advisor", "description": "Synthesizes findings into recommendations", "system_prompt": """Synthesize the technical research and security analysis into actionable strategic recommendations. Provide a timeline for action and prioritize recommendations by urgency and impact.""", "model_name": "gpt-4.1", "role": "advisor", "max_loops": 1, "max_tokens": 5000, "temperature": 0.4 } ] ) print(research_team) ``` ## Best Practices ### 1. Craft Effective Search-Oriented Prompts Structure your system prompts to leverage search capabilities: ```python theme={null} system_prompt = """You are a research assistant with web search capabilities. When responding to queries: 1. SEARCH: First search for relevant, current information 2. VERIFY: Cross-reference findings across multiple sources 3. SYNTHESIZE: Combine information into a coherent response 4. CITE: Always mention your sources 5. QUALIFY: Note any uncertainties or conflicting information Prioritize recent sources (within the last year) for time-sensitive topics.""" ``` ### 2. Match Prompt Depth to Task Complexity Since `auto_search` has no tunable result-count or snippet-length parameters, control research depth through the system prompt instead — instruct the agent how many sources to consult and how thoroughly to synthesize them for the task at hand (quick fact lookup vs. comprehensive analysis). ### 3. Use Appropriate Temperature Settings * **Factual research** (0.1-0.2): When accuracy is critical * **Balanced analysis** (0.3-0.4): For synthesis and interpretation * **Creative exploration** (0.5-0.7): For brainstorming and ideation ### 4. Handle Time-Sensitive Information For topics where recency matters, include temporal context in your task: ```python theme={null} "task": "What are the latest AI safety developments from the past 3 months?" ``` ### 5. Request Source Citations Include citation requirements in your system prompt: ```python theme={null} system_prompt = """... Always cite sources in your response using this format: - [Source Name](URL) - Key finding from this source End your response with a 'Sources' section listing all references.""" ``` ## Error Handling ```python theme={null} import requests import time def search_with_retry(payload, headers, max_retries=3): """Execute search request with exponential backoff retry.""" base_url = "https://api.swarms.world" for attempt in range(max_retries): try: response = requests.post( f"{base_url}/v1/agent/completions", headers=headers, json=payload, timeout=120 # Longer timeout for search operations ) if response.status_code == 200: result = response.json() return { "success": True, "outputs": result.get("outputs"), "usage": result.get("usage") } elif response.status_code == 429: # Rate limited - wait and retry wait_time = 2 ** attempt print(f"Rate limited. Waiting {wait_time}s before retry...") time.sleep(wait_time) continue elif response.status_code == 503: # Service temporarily unavailable wait_time = 5 * (attempt + 1) print(f"Service unavailable. Waiting {wait_time}s...") time.sleep(wait_time) continue else: return { "success": False, "error": f"HTTP {response.status_code}: {response.text}" } except requests.exceptions.Timeout: print(f"Request timed out. Attempt {attempt + 1}/{max_retries}") continue except requests.exceptions.ConnectionError: print(f"Connection error. Attempt {attempt + 1}/{max_retries}") time.sleep(2 ** attempt) continue return { "success": False, "error": "Max retries exceeded" } # Usage result = search_with_retry(payload, headers) if result["success"]: print(result["outputs"]) else: print(f"Error: {result['error']}") ``` ## Response Format Search-enabled agents return the standard `/v1/agent/completions` response shape. The `outputs` field contains the agent's final synthesized answer (including any citations the agent chose to include in its text) — there is no separate structured `search_results` array; source handling happens inside the agent's tool call and reasoning, not as a distinct response field. ```json theme={null} { "job_id": "agent-...", "success": true, "name": "Research Agent", "outputs": "Your comprehensive research response with synthesized information...", "usage": { "input_tokens": 500, "output_tokens": 1200, "total_tokens": 1700, "img_cost": 0.0, "total_cost": 0.025 }, "timestamp": "2024-01-15T00:00:00Z" } ``` Note: the `total_cost` in `usage` reflects token costs only. The flat \$0.04 `auto_search` tool fee is deducted from your account credits separately and does not appear in this `usage` object. ## Cost Optimization Each `auto_search` tool call costs a flat \$0.04 (`search_cost`), deducted from your account credits, on top of normal token costs. Optimize usage with these strategies: 1. **Only enable search when needed**: Omit `tools_enabled` (or leave `auto_search` out of it) for tasks that don't require live web data — you'll skip the \$0.04 fee entirely. 2. **Cache research results**: Store responses for repeated similar queries instead of re-running search. 3. **Use appropriate models**: Use `gpt-4.1-mini` for simpler research tasks to reduce token costs. 4. **Limit output length**: Set a smaller `max_tokens` on `agent_config` to control response length and cost. ```python theme={null} # Cost-efficient configuration for simple queries efficient_config = { "agent_config": { "model_name": "gpt-4.1-mini", # Lower cost model "max_tokens": 2000 # Limit output length }, "tools_enabled": ["auto_search"] } ``` ## Related Resources * [Search-Enabled Agents](/docs/examples/examples/search-enabled) - Basic search configuration * [Multi-Agent Workflows](/docs/documentation/multi-agent/swarm_types) - Combining search with swarms # Introduction to The Swarms API Python Client Source: https://docs.swarms.ai/docs/guides/guides/first Learn how to set up the Swarms API client and perform basic operations like checking health, models, and rate limits. This guide covers everything you need to get started with the Swarms API Python Client, from initial setup through advanced multi-agent implementations. It provides clear instructions, practical examples, and best practices to help you effectively leverage multi-agent collaboration in your projects. ### Key Features and Capabilities The Swarms API Python Client offers several distinctive features that set it apart from other AI development tools: **Type Safety and Modern Python Support**: The library provides complete type definitions for all request parameters and response fields, ensuring that developers can catch errors at compile time rather than runtime. Built specifically for Python 3.8 and higher versions, it leverages modern Python features including async/await support for concurrent operations. **Dual Client Architecture**: The library offers both synchronous and asynchronous clients powered by httpx, allowing developers to choose the most appropriate approach for their specific use case. This flexibility is crucial for applications that need to handle multiple concurrent requests or integrate with existing asynchronous codebases. **Comprehensive API Coverage**: Every endpoint of the Swarms API is accessible through the client library, providing developers with complete control over their multi-agent systems. This includes swarm creation, management, monitoring, and advanced configuration options. **Environment Integration**: The client seamlessly integrates with environment variables and .env files, making it easy to manage API keys and configuration settings across different deployment environments. ## Installation and Environment Setup Getting started with the Swarms API Python Client is straightforward, requiring just a few simple steps to get your development environment ready. ### Installing the Client Library The installation process is streamlined through Python's package manager. Execute the following command in your terminal or command prompt: ```bash theme={null} pip install swarms-client ``` For users who prefer to ensure they have the latest version, or those working in environments where package versions might be cached, the following command provides an upgrade flag: ```bash theme={null} pip3 install -U swarms-client ``` This installation will automatically handle all dependencies, including httpx for HTTP operations, pydantic for data validation, and other essential libraries required for the client to function properly. ### Obtaining Your API Key Before you can begin using the Swarms API, you'll need to obtain an API key, which serves as your authentication credential for accessing the service. The process is designed to be user-friendly and secure: 1. Navigate to the Swarms platform at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create a new account if you don't already have one, or sign in to your existing account 3. Once logged in, locate the API key generation section 4. Generate a new API key, ensuring you copy it immediately as it may not be displayed again for security reasons 5. Store the API key securely, preferably using environment variables or a secure key management system ### Environment Configuration Proper environment configuration is crucial for both security and ease of development. Create a `.env` file in your project's root directory and add your API key: ``` SWARMS_API_KEY=your_api_key_here ``` This approach keeps sensitive information out of your source code and makes it easy to manage different API keys across development, staging, and production environments. For loading environment variables in your Python application, you'll also need to install the python-dotenv package if it's not already available: ```bash theme={null} pip install python-dotenv ``` ## Client Initialization and Basic Configuration Once you have installed the library and configured your environment, initializing the Swarms client is straightforward. The client supports multiple initialization patterns to accommodate different development scenarios. ### Basic Client Setup The simplest way to initialize the client uses environment variables for configuration: ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Initialize client with automatic environment variable detection client = SwarmsClient() ``` This approach automatically looks for the `SWARMS_API_KEY` environment variable, making your code cleaner and more secure. ### Direct API Key Configuration For scenarios where you need to specify the API key directly, perhaps when loading from a different source or for testing purposes: ```python theme={null} client = SwarmsClient(api_key="your_api_key_here") ``` ### Advanced Configuration Options The client also supports advanced configuration for specialized use cases: ```python theme={null} client = SwarmsClient( api_key=os.getenv("SWARMS_API_KEY"), base_url="https://api.swarms.world", # Custom base URL if needed timeout=30.0, # Request timeout in seconds ) ``` These configuration options allow you to customize the client behavior to match your specific requirements, including custom timeout values for long-running operations or alternative base URLs for different environments. ### Verifying Your Setup Before proceeding with agent creation, it's important to verify that your client is properly configured and can communicate with the Swarms API. The following code demonstrates how to perform basic health checks and gather information about your API access: ```python theme={null} import os import json from dotenv import load_dotenv from swarms_client import SwarmsClient # Load environment variables load_dotenv() # Initialize the client client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Check API health status health_status = client.health.check() print("API Health Status:") print(json.dumps(health_status, indent=4)) # List available models available_models = client.models.list_available() print("\nAvailable Models:") print(json.dumps(available_models, indent=4)) # Check current rate limits rate_limits = client.client.rate.get_limits() print("\nRate Limits:") print(json.dumps(rate_limits, indent=4)) # Get swarm availability status swarm_availability = client.swarms.check_available() print("\nSwarm Availability:") print(json.dumps(swarm_availability, indent=4)) ``` This verification script provides valuable information about your API access, including the health status of the service, available AI models, your current rate limit usage, and the availability of swarm services. ## Running Your First Single Agent With your client properly configured and verified, you're now ready to create and run your first AI agent. Single agents are the building blocks of more complex multi-agent systems, and understanding how to configure and deploy them is essential for leveraging the full power of the Swarms API. ### Understanding Agent Configuration Every agent in the Swarms system requires several key parameters that define its behavior, capabilities, and role within the larger system. These parameters include: **Agent Name and Description**: These provide human-readable identifiers and explanations of the agent's purpose, making it easier to manage and understand complex multi-agent systems. **System Prompt**: This is perhaps the most critical parameter, as it defines the agent's personality, expertise, and behavioral guidelines. A well-crafted system prompt can dramatically improve the agent's performance and ensure it behaves in accordance with your requirements. **Model Selection**: The choice of underlying AI model affects the agent's capabilities, response quality, and processing speed. Different models excel in different areas, so selecting the appropriate model for your use case is crucial. **Operational Parameters**: These include settings like maximum loops, token limits, and temperature values that control how the agent processes information and generates responses. ### Creating a Simple Analysis Agent Let's start with a practical example by creating a single agent designed to perform text analysis tasks: ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv load_dotenv() client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Define the task for our agent analysis_task = """ Analyze the following customer feedback and provide insights: "The new product update has improved performance significantly, but the user interface changes are confusing. Many customers are struggling to find features they previously used daily. While the speed improvements are appreciated, the learning curve is steep." Please provide: 1. Key sentiment indicators 2. Specific pain points mentioned 3. Positive aspects highlighted 4. Recommendations for improvement """ # Create and run a single agent response = client.swarms.run( name="Customer Feedback Analyzer", description="Analyzes customer feedback to extract insights and recommendations", swarm_type="SequentialWorkflow", task=analysis_task, agents=[ { "agent_name": "Feedback Analyst", "description": "Specializes in analyzing customer feedback for business insights", "system_prompt": """You are a customer experience analyst with expertise in feedback interpretation. Analyze customer feedback systematically, identifying both positive and negative aspects. Provide actionable insights and specific recommendations based on the feedback content. Structure your analysis clearly and professionally.""", "model_name": "groq/openai/gpt-oss-120b", "role": "analyst", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, } ], ) print("Analysis Results:") print(response) ``` This example demonstrates how to create a focused, single-purpose agent that can provide valuable business insights. The agent is configured with specific parameters that optimize it for analytical tasks, including a relatively low temperature value for consistent, focused responses. ### Understanding Agent Parameters in Detail Each parameter in the agent configuration serves a specific purpose: **max\_loops**: This parameter controls how many times the agent will iterate on its response. For simple tasks, a value of 1 is often sufficient, while more complex problems might benefit from multiple iterations. **max\_tokens**: This sets the maximum length of the agent's response, helping control costs and ensuring responses remain focused and relevant. **temperature**: This parameter controls the creativity and randomness in the agent's responses. Lower values (0.1-0.3) produce more consistent, focused outputs, while higher values (0.7-0.9) generate more creative and varied responses. **role**: While not strictly enforced by the API, the role parameter helps organize agents within larger systems and can be used for filtering and management purposes. ## Scaling to Multiple Agents While single agents can handle straightforward tasks effectively, the true power of the Swarms API becomes apparent when multiple agents work together on complex problems. Multi-agent systems enable specialization, parallel processing, and sophisticated workflows that can tackle challenges that would be difficult or impossible for a single agent to handle effectively. ### Understanding Multi-Agent Workflows The Swarms API supports different types of multi-agent workflows, each optimized for specific use cases: **Sequential Workflows**: In this pattern, agents work in a specific order, with each agent building upon the work of the previous one. This is ideal for tasks that require a logical progression, such as research followed by analysis followed by report generation. **Concurrent Workflows**: This pattern allows multiple agents to work simultaneously on different aspects of the same problem, then combine their results. This approach is excellent for tasks that can be parallelized, such as analyzing multiple data sources or generating content from different perspectives. ### Building Your First Multi-Agent System Let's create a comprehensive multi-agent system designed to handle a complex business analysis task. This example will demonstrate how different agents can specialize in specific aspects of a problem while working together toward a common goal: ```python theme={null} import os from swarms_client import SwarmsClient from dotenv import load_dotenv load_dotenv() client = SwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Define a complex business analysis task business_analysis_task = """ A tech startup is considering expanding into the European market. They currently operate in North America and have the following characteristics: - SaaS product with $2M ARR - 50-person team - B2B focus on mid-market companies - Strong growth (200% YoY) - Limited international experience Analyze the expansion opportunity and provide comprehensive recommendations including market analysis, operational considerations, financial projections, and risk assessment. """ # Create a multi-agent system for comprehensive business analysis expansion_analysis = client.swarms.run( name="EU Market Expansion Analysis", description="Multi-agent system for comprehensive market expansion analysis", swarm_type="SequentialWorkflow", task=business_analysis_task, agents=[ { "agent_name": "Market Research Specialist", "description": "Analyzes target markets, competition, and opportunities", "system_prompt": """You are a senior market research analyst with deep expertise in European markets and SaaS business models. Analyze market size, competitive landscape, regulatory considerations, and customer segments. Provide data-driven insights about market entry strategies and potential challenges.""", "model_name": "groq/openai/gpt-oss-120b", "role": "researcher", "max_loops": 1, "max_tokens": 6144, "temperature": 0.2, }, { "agent_name": "Operations Strategist", "description": "Evaluates operational requirements and implementation strategies", "system_prompt": """You are an operations strategy consultant specializing in international expansion for tech companies. Focus on operational requirements, team structure, legal and compliance needs, technology infrastructure, and implementation timeline. Consider both challenges and solutions for scaling operations internationally.""", "model_name": "groq/openai/gpt-oss-120b", "role": "strategist", "max_loops": 1, "max_tokens": 6144, "temperature": 0.3, }, { "agent_name": "Financial Analyst", "description": "Provides financial modeling and investment analysis", "system_prompt": """You are a senior financial analyst with expertise in SaaS metrics and international expansion financial modeling. Develop financial projections, analyze investment requirements, assess ROI potential, and identify key financial risks and opportunities. Focus on realistic scenarios and key financial assumptions.""", "model_name": "groq/openai/gpt-oss-120b", "role": "financial_analyst", "max_loops": 1, "max_tokens": 6144, "temperature": 0.2, }, { "agent_name": "Risk Assessment Specialist", "description": "Evaluates potential risks and mitigation strategies", "system_prompt": """You are a risk management consultant specializing in international business expansion. Identify and analyze potential risks including market risks, operational risks, financial risks, regulatory risks, and competitive risks. For each risk identified, provide specific mitigation strategies and contingency planning recommendations.""", "model_name": "groq/openai/gpt-oss-120b", "role": "risk_analyst", "max_loops": 1, "max_tokens": 5120, "temperature": 0.3, }, { "agent_name": "Strategic Synthesizer", "description": "Combines insights from all agents into cohesive recommendations", "system_prompt": """You are a senior strategy consultant who synthesizes complex analysis from multiple sources into clear, actionable recommendations. Review all previous analyses and create a comprehensive strategic recommendation that includes executive summary, key findings, recommended approach, timeline, resource requirements, and success metrics.""", "model_name": "groq/openai/gpt-oss-120b", "role": "synthesizer", "max_loops": 1, "max_tokens": 8192, "temperature": 0.4, } ], ) print("Comprehensive Business Analysis:") print(expansion_analysis) ``` This multi-agent system demonstrates several important concepts: **Specialization**: Each agent has a specific area of expertise and a tailored system prompt that guides its analysis in that domain. **Sequential Processing**: The agents work in a logical sequence, with later agents building upon the insights generated by earlier ones. **Varying Complexity**: Different agents have different max\_loops and max\_tokens settings based on the complexity of their assigned tasks. **Synthesis**: The final agent serves as a synthesizer, combining insights from all previous agents into a cohesive, actionable recommendation. ### Advanced Multi-Agent Patterns As you become more comfortable with multi-agent systems, you can explore more sophisticated patterns and configurations: ```python theme={null} # Example: Concurrent analysis with multiple perspectives market_research_swarm = client.swarms.run( name="Multi-Perspective Market Analysis", description="Concurrent analysis from different market perspectives", swarm_type="ConcurrentWorkflow", task="Analyze the potential for AI-powered customer service solutions in the healthcare sector", agents=[ { "agent_name": "Technology Analyst", "description": "Analyzes technological feasibility and requirements", "system_prompt": "You are a healthcare technology analyst. Focus on technical requirements, integration challenges, and technology trends.", "model_name": "groq/openai/gpt-oss-120b", "role": "tech_analyst", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, }, { "agent_name": "Healthcare Industry Expert", "description": "Provides healthcare sector insights and requirements", "system_prompt": "You are a healthcare industry consultant. Focus on industry-specific needs, regulations, and adoption patterns.", "model_name": "groq/openai/gpt-oss-120b", "role": "industry_expert", "max_loops": 1, "max_tokens": 4096, "temperature": 0.3, }, { "agent_name": "Customer Experience Researcher", "description": "Analyzes user experience and adoption factors", "system_prompt": "You are a UX researcher specializing in healthcare technology. Focus on user adoption, experience design, and patient satisfaction factors.", "model_name": "groq/openai/gpt-oss-120b", "role": "ux_researcher", "max_loops": 1, "max_tokens": 4096, "temperature": 0.4, } ], ) ``` ## Advanced Features and Best Practices As your experience with the Swarms API grows, you'll want to leverage more advanced features and implement best practices that ensure optimal performance, reliability, and maintainability of your multi-agent systems. ### Asynchronous Operations For applications that need to handle multiple concurrent requests or integrate with existing asynchronous codebases, the Swarms API client provides full asynchronous support: ```python theme={null} import asyncio from swarms_client import AsyncSwarmsClient async def run_concurrent_analysis(): client = AsyncSwarmsClient(api_key=os.getenv("SWARMS_API_KEY")) # Define multiple analysis tasks tasks = [ client.swarms.run( name="Financial Analysis", description="Analyze financial performance", swarm_type="SequentialWorkflow", task="Analyze Q4 financial results", agents=[...] # Agent configuration ), client.swarms.run( name="Market Analysis", description="Analyze market conditions", swarm_type="SequentialWorkflow", task="Analyze current market trends", agents=[...] # Agent configuration ), client.models.list_available() ] # Execute all tasks concurrently results = await asyncio.gather(*tasks) return results # Run the async operations results = asyncio.run(run_concurrent_analysis()) ``` ### Monitoring and Management Effective monitoring and management of your multi-agent systems is crucial for production deployments. The Swarms API provides several endpoints for monitoring system health and usage: ```python theme={null} # Monitor system health and usage def monitor_system_status(client): # Check API health health_status = client.health.check() if health_status['status'] != 'healthy': print(f"API health issue detected: {health_status}") # Monitor rate limits rate_limits = client.client.rate.get_limits() usage_percentage = (rate_limits['current_usage'] / rate_limits['requests_per_minute']) * 100 if usage_percentage > 80: print(f"High API usage detected: {usage_percentage:.1f}% of rate limit") # Check swarm availability availability = client.swarms.check_available() if not availability.get('available', False): print("Swarm services currently unavailable") # Review recent logs logs = client.swarms.get_logs() recent_errors = [log for log in logs if log.get('level') == 'error'] if recent_errors: print(f"Recent errors detected: {len(recent_errors)}") # Run monitoring monitor_system_status(client) ``` ### Performance Optimization To optimize the performance of your multi-agent systems, consider these strategies: **Model Selection**: Different models have different performance characteristics. Choose models that match your specific requirements for speed, quality, and cost. **Token Management**: Carefully configure max\_tokens based on your needs. Excessive token limits increase costs and processing time, while insufficient limits may truncate important responses. **Temperature Tuning**: Adjust temperature values based on the type of task. Use lower temperatures (0.1-0.3) for factual, analytical tasks and higher temperatures (0.5-0.8) for creative tasks. ## Conclusion and Next Steps The Swarms API Python Client marks a significant step forward in making advanced multi-agent AI systems accessible to developers and organizations of all sizes. Throughout this guide, we've covered the essential concepts, practical implementation strategies, and advanced techniques needed to harness the full power of multi-agent collaboration. From single-agent implementations to complex orchestrations, the platform’s scalability and flexibility enable you to create specialized agents that work together to solve problems that would be difficult or impossible for traditional single-agent approaches. Key takeaways include the importance of well-crafted system prompts, selecting the right workflow types (sequential or concurrent), and ensuring robust error handling, monitoring, and performance optimization for production-ready systems. Looking ahead, the Swarms API is poised to evolve with new capabilities such as enhanced agent coordination, more sophisticated workflow patterns, improved performance features, and expanded model options. Its commitment to comprehensive Python client support and a strong developer experience makes it an excellent choice for integrating advanced AI into a wide range of applications—from customer service automation and content generation to data analysis and business intelligence. As you continue to explore and implement multi-agent systems, remember that starting simple and gradually increasing complexity is often the most effective approach. The examples and patterns in this guide provide a solid foundation for building scalable, adaptable solutions that can grow with your needs. # From Prototype to $10K MRR: Monetize Your Agent on the Swarms Marketplace Source: https://docs.swarms.ai/docs/guides/guides/monetize-agent-on-marketplace A builder-to-builder playbook for packaging a working agent into a paid marketplace listing, tokenizing it for creator fees, and earning recurring revenue. ## TL;DR * **Build** a focused agent that solves one expensive, repetitive task — not a general assistant. * **Publish** it to the Swarms Marketplace with `POST /api/add-agent` (price it as a paid listing, not free). * **Monetize** through a sharp listing page — outcome-first copy, before/after examples, monthly pricing. * **Tokenize** through `POST /api/token/launch` so the agent has a Solana mint and you accrue creator fees. * **Promote** through three concrete channels (Twitter thread, free public demo, weekly subreddit posts) and pull earnings with `POST /api/product/claimfees`. The numbers at the end are honest: \$10K MRR is reachable, but it usually takes 3–6 months of consistent posting, a polished listing, and a working public demo. This guide is the path. *** ## Why Most Agents Never Earn a Dollar Most agent builders ship code, not products. They write a great system prompt, get it working on their own data, push the repo, and then wait. There's no listing page that explains the outcome in 10 seconds, no pricing, no demo a stranger can run without writing Python, and no distribution beyond a tweet at launch. The Swarms Marketplace handles the distribution layer — the discovery surface, the payments rail, the tokenized fee structure — but it can't write your one-paragraph value prop or your before/after screenshots. That's the product framing, and it's what separates the listings that earn from the listings that don't. The builders on the marketplace pulling real revenue all did the same boring thing: they treated the agent like a SaaS product and the listing page like a landing page. *** ## Meet Maya — A Working Example Maya is a freelance ops consultant. Her clients send her quarterly P\&Ls and operational spreadsheets that are uniformly disastrous — merged cells, inconsistent date formats, currency mixed with text, blank columns nobody remembers creating. She used to spend the first 90 minutes of every engagement just cleaning the file. Six months ago she built an agent for herself: feed it a messy CSV, it returns a clean, normalised CSV plus a summary of what it changed. She called it the Spreadsheet Cleaner Agent. A few of her clients saw it run, and three of them asked if they could just send her files directly and pay her to run them. That's the moment most consultants either say yes (and trade their time for slightly more money) or shrug and move on. Maya wants the third option: turn the agent into recurring revenue without quitting consulting. She wants the agent to be a product strangers can buy, while she keeps the consulting practice running on the side. The rest of this guide walks Maya through exactly that — packaging the agent for the marketplace, publishing it via the Agents API, writing a listing page that actually converts, tokenizing it for ongoing creator fees, and the three marketing motions she'll run for the next six months. *** ## Step 1: Package the Agent Before anything ships to the marketplace, the agent has to be a clean object: a focused system prompt, an explicit model choice, a documented input shape, and a documented output shape. This is what Maya's agent looks like as a deployable Swarms `Agent`: ```python theme={null} from swarms import Agent SYSTEM_PROMPT = """You are the Spreadsheet Cleaner Agent. Your job is to take a messy financial or operational spreadsheet (CSV or TSV) and return: 1) A cleaned CSV with these guarantees: - All dates normalised to ISO 8601 (YYYY-MM-DD) - All currency normalised to USD as a float (no symbols, no commas) - One header row, snake_case column names, no merged cells - Empty/whitespace-only rows removed - All numeric columns typed as numbers, not strings - Inferred but missing column names labelled column_1, column_2, ... 2) A short CHANGE_LOG section describing exactly what you changed, grouped by column. Be specific: name the columns, count the rows affected, and call out any data you dropped. 3) A QUALITY_FLAGS section listing rows or columns the user should review manually (suspected duplicates, currency you couldn't infer, dates older than 1970, etc.). Output format (strict): ---CLEANED_CSV--- <the cleaned CSV> ---CHANGE_LOG--- <bulleted list> ---QUALITY_FLAGS--- <bulleted list> Never invent data. If a value is ambiguous, leave it and flag it.""" spreadsheet_cleaner = Agent( agent_name="Spreadsheet-Cleaner-Agent", agent_description=( "Takes a messy financial spreadsheet and returns a cleaned " "CSV plus a change log. Built for ops consultants, " "bookkeepers, and finance teams." ), model_name="gpt-4.1-mini", system_prompt=SYSTEM_PROMPT, max_loops=1, max_tokens=8192, ) ``` Three things Maya did right that most builders skip: 1. **The output format is strict and parseable.** A buyer can pipe the result straight into a script. Free-form prose responses are not products. 2. **The model is `gpt-4.1-mini`, not `gpt-4.1`.** At a \$19/mo subscription, margin matters. Mini handles structured cleanup well and keeps her unit economics healthy. 3. **The system prompt has a refusal rule** — "Never invent data" — which is exactly the kind of trust signal buyers screenshot and share. Run it locally a few times against three real-but-anonymised input files. Save the inputs and outputs — those become the before/after examples on the listing page. *** ## Step 2: Publish to the Marketplace via the Agents API The Swarms Marketplace lives at `https://swarms.world`. The agent listing endpoint is `POST /api/add-agent`, authenticated with a bearer token. Maya's first publish call looks like this: ```python theme={null} import os import requests API_KEY = os.environ["SWARMS_API_KEY"] payload = { "name": "Spreadsheet Cleaner Agent", "description": ( "Upload a messy financial or operational CSV. Get back a " "cleaned CSV with normalised dates, normalised currency, " "snake_case columns, and a change log. Built for ops " "consultants, bookkeepers, and finance teams who spend the " "first hour of every engagement cleaning files." ), "language": "python", "agent": SYSTEM_PROMPT, # the system prompt from Step 1 "useCases": [ { "title": "Quarterly P&L Cleanup", "description": ( "Drop a messy quarterly P&L export. Receive a cleaned " "CSV with normalised dates and currency, plus a " "change log of every modification." ), }, { "title": "Bookkeeper Handoff", "description": ( "Normalise a client's raw bank-export CSV so it can " "be imported into QuickBooks or Xero without manual " "column-mapping." ), }, { "title": "Operational Dashboard Prep", "description": ( "Take a multi-sheet ops export and return one clean, " "typed CSV ready to load into a BI tool." ), }, ], "tags": "spreadsheet,csv,cleaning,finance,ops,bookkeeping", "category": "finance", "is_free": False, "price_usd": 19.00, "seller_wallet_address": os.environ["SOLANA_WALLET_ADDRESS"], } resp = requests.post( "https://swarms.world/api/add-agent", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, timeout=60, ) data = resp.json() resp.raise_for_status() print("Listing URL:", data["listing_url"]) print("Agent ID:", data["id"]) ``` A few notes on the choices in that payload: * **`category: "finance"`** — Maya picked the closest existing category. Listings in a known category get filtered traffic; listings in `null` get nothing. * **`is_free: False` and `price_usd: 19.00`** — paid from day one. You can always discount; you cannot easily flip a free agent to paid without losing the "thousands of free users" who never paid you anyway. * **`useCases`** — three concrete, named scenarios. Buyers don't read prose, they scan for the use case that matches them. * **`seller_wallet_address`** — a Solana wallet she controls. Payouts and creator fees route here. On success, the response includes the public `listing_url`. Open it in a browser, scroll like a buyer would, and ask: *would I pay \$19/mo for this based on the page alone?* If no, fix the page before you spend a dollar promoting it. Full reference: [Agents API](/docs/marketplace/agents-api). *** ## Step 3: Write a Listing Page That Converts The listing page is the one thing every paying user sees and most builders ignore. The conversion math is unforgiving — at a 2% conversion rate, every visitor you waste on a confusing page costs you compounding revenue. Four rules that the highest-earning listings on the marketplace all follow: 1. **Lead with the outcome, not the technology.** "Returns a cleaned CSV plus a change log" beats "Uses GPT-4o-mini with a structured output prompt to perform CSV normalisation." Buyers don't care what model you used. 2. **Show three concrete before/after examples.** Use the inputs you saved from Step 1. A real screenshot of a messy spreadsheet next to the cleaned output is worth a thousand bullet points. Anonymise the data; keep the realism. 3. **Price as a monthly subscription, not per-call.** Per-call pricing creates buyer anxiety ("will this run cost me \$3 or \$300?"). A flat monthly subscription anchors the value at the *outcome* (an ops consultant saves 6 hours per client per month — that's \$19 of obvious value). The marketplace's subscription tier is launching shortly; price into it from day one. 4. **Under 200 words of copy.** If a buyer can't decide in 200 words, more words won't fix it. Headline, three bullets of what you get, three before/after thumbnails, price, button. Maya's final listing copy, in full: > **Spreadsheet Cleaner Agent** > > *Upload any messy financial CSV. Get back a clean one in 30 seconds.* > > * **Normalised** — dates in ISO 8601, currency in USD floats, snake\_case columns > * **Audited** — every change is logged so you (or your client) can review it > * **Flagged** — suspected duplicates and ambiguous values are surfaced, never silently dropped > > Built for ops consultants, bookkeepers, and finance teams who spend the first hour of every engagement fixing the file before the work can start. > > **\$19/month — unlimited cleanups.** Use the `POST /api/edit-agent` endpoint to iterate on the listing without re-creating it. Iterate weekly for the first month. *** ## Step 4: Tokenize for Creator Fees via the Launchpad The marketplace subscription is one revenue stream. Tokenizing the agent unlocks a second one: **creator fees** that accrue every time the agent's token trades on its bonding curve. This is what separates the marketplace from every other agent directory — the agent itself becomes a Solana asset, and you, as the creator, keep a share of trading fees in perpetuity. The fastest path is `POST /api/token/launch`, which creates the listing and the token in a single request. Maya already has the listing from Step 2 — for new agents, the Launchpad endpoint does both at once. Here's the call: ```python theme={null} import os import requests API_KEY = os.environ["SWARMS_API_KEY"] SOLANA_PRIVATE_KEY = os.environ["SOLANA_PRIVATE_KEY"] payload = { "name": "Spreadsheet Cleaner Agent", "description": ( "Upload a messy financial CSV. Get back a clean one — " "normalised dates, normalised currency, snake_case columns, " "full change log. Built for ops consultants and bookkeepers." ), "ticker": "CLEAN", "private_key": SOLANA_PRIVATE_KEY, "image": "https://your-cdn.example.com/clean-agent-icon.png", "fee_selection": "market", # "frenzy" for 2x fees + leaderboard "quote_mint": "SOL", # or "USDC" } resp = requests.post( "https://swarms.world/api/token/launch", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, timeout=120, ) data = resp.json() resp.raise_for_status() print("Listing:", data["listing_url"]) print("Token mint:", data["token_address"]) print("Pool:", data.get("pool_address")) ``` A few things to understand plainly before you launch: * **Token launch costs \~0.04 SOL.** Fund the wallet associated with `private_key` first. * **Creator fees vs. revenue fees are different things.** Revenue fees are what the marketplace charges on subscription payments (5–15% depending on tier — see the [Monetization Guide](/docs/marketplace/monetize)). Creator fees are what your agent's *token* accrues from on-chain trading on the bonding curve. Both flow to you. You don't have to choose one. * **`fee_selection: "frenzy"` doubles the trading fees** and puts your token on the Frenzy leaderboard, which is its own discovery surface. Use it if you have a marketing push planned for launch day; otherwise stick with `"market"`. * **Never put a real private key in source control.** Use environment variables or a secret manager. The `private_key` is only used to sign the on-chain transaction. Full reference: [Token Launch API](/docs/marketplace/token-launch-api) and the [tokenization details](/docs/marketplace/tokenization_details). *** ## Step 5: The Three Marketing Motions That Actually Work The marketplace surfaces discovery; you still have to bring people to the listing. Out of the dozen things builders try, three actually move the needle. Run all three, weekly, for six months. ### (a) The before/after Twitter thread Once a week, run the agent on a real (anonymised) file from a friend or a client. Post the input as the first image, the output as the second, the change log as the third. The thread is the proof — strangers see exactly what they'll get. Pin the best one. The format that converts: ``` 1/ I clean ~30 client spreadsheets a month. This used to take 90 min each. Now my agent does it in 30 seconds. Here's what a real run looked like this morning. [image: messy input] 2/ Same file, 30 seconds later. [image: cleaned output] 3/ And the change log — every modification, by column, with row counts. This is the part my clients actually care about. [image: change log] 4/ Live here: swarms.world/agent/<your-id>. $19/mo, unlimited runs. ``` Don't promote every thread. Make the agent the protagonist of three threads, then a fourth thread about something else entirely (a lesson, a failure mode, a tool you use). Variety is what keeps you from sounding like an ad. ### (b) A free public demo page This is the single highest-leverage thing you can build. A one-page web app where anyone can upload a small CSV and see the agent run — calling your marketplace agent under the hood. No login. No pricing wall. Just the agent doing the thing on their data. ```python theme={null} # Sketch — a FastAPI endpoint your demo page calls. # Marketplace agents can be invoked via the standard Swarms API # once you have the agent's system prompt in your code. from fastapi import FastAPI, UploadFile from swarms import Agent app = FastAPI() demo_agent = Agent( agent_name="Spreadsheet-Cleaner-Demo", model_name="gpt-4.1-mini", system_prompt=SYSTEM_PROMPT, # same as your listed agent max_loops=1, ) @app.post("/demo") async def demo(file: UploadFile): raw = (await file.read()).decode("utf-8") # Cap demo input to keep your spend bounded. if len(raw) > 50_000: return {"error": "Demo limited to 50KB. Subscribe for unlimited."} cleaned = demo_agent.run(f"Clean this CSV:\n\n{raw}") return {"cleaned": cleaned} ``` The demo converts because the buyer has already experienced the value before they're asked to pay. Cap the input size so the free demo doesn't sink your token budget, and put a "Subscribe — \$19/mo" CTA above the result. ### (c) One subreddit per week, with genuine commentary Identify the three subreddits where your buyers actually hang out — for Maya, that's `r/bookkeeping`, `r/fpanda`, and `r/Accounting`. Once a week, find a thread where someone is complaining about exactly the problem your agent solves, and reply with genuine help. Sometimes you mention the agent; sometimes you don't. The point is to be a real participant, not a promoter. Marketplace listings linked from a comment that opens with "I built this for myself, happy to share how I clean these" convert \~10x better than the same listing linked from a top-level "check out my new tool" post. Three motions, one hour per week each. The compounding is real but slow — most accounts that hit traction did six months of this before the curve bent. *** ## Step 6: Track Revenue with the Claim Fees API The marketplace handles subscription payments automatically. The token side — your creator fees from on-chain trading — accrues on-chain and is claimed on demand. The `POST /api/product/claimfees` endpoint returns both the claimed amount and a full breakdown of historical earnings, so you can use it as your dashboard query: ```python theme={null} import os import requests payload = { "ca": os.environ["TOKEN_MINT_ADDRESS"], # from Step 4 response "privateKey": os.environ["SOLANA_PRIVATE_KEY_BASE58"], } resp = requests.post( "https://swarms.world/api/product/claimfees", headers={"Content-Type": "application/json"}, json=payload, timeout=60, ) data = resp.json() resp.raise_for_status() if data.get("amountClaimedSol") is not None: print(f"Just claimed: {data['amountClaimedSol']:.4f} SOL") if data.get("fees"): print(f"Unclaimed: {data['fees']['unclaimedSol']:.4f} SOL") print(f"Lifetime claimed: {data['fees']['claimedSol']:.4f} SOL") print(f"Lifetime total: {data['fees']['totalSol']:.4f} SOL") print("Tx signature:", data.get("signature")) ``` Run it weekly. Log the lifetime total to a spreadsheet (which the Spreadsheet Cleaner could clean, but that would be too on-the-nose). The signature is the on-chain proof if you need to reconcile. Full reference: [Claim Fees API](/docs/marketplace/claim-fees-api). *** ## The Math at \$10K MRR Let's be honest about what \$10K MRR looks like from a pure-subscription perspective, before token fees are layered on top. At a \$19/month subscription, you need \~526 paying users. That's a real number, not a vanity number — and the funnel that gets you there is not magic: | Stage | Conversion | Required volume | | ------------------------------------ | ---------- | --------------------------- | | Monthly subscribers needed | — | **526** | | Trial-to-paid conversion | 25% | 2,100 trials/month | | Listing visitors to trial | 10% | 21,000 visitors/month | | Top-of-funnel impressions to visitor | \~5% | \~420,000 impressions/month | | **Or: direct visitor-to-paid** | **2%** | **\~26,300 visitors/month** | Two ways to read this table. The pessimistic read: 26K monthly visitors is a meaningful audience. The optimistic read: 26K is \~870 visitors per day, which is what a single decent Twitter thread can deliver, and the three motions in Step 5 compound. Builders earning real revenue on the marketplace today do not have a million followers. They have a focused listing, a working public demo, and six months of consistent posting in the right three places. Layer the token creator fees on top. If your agent's token sees even modest secondary trading, the fees from `POST /api/product/claimfees` add a non-trivial second stream. The builders treating both streams as serious — subscription + creator fees — are the ones whose numbers get interesting. \$10K MRR in 3 months is unlikely. \$10K MRR in 6–9 months for a builder running the playbook seriously is the realistic target. *** ## Common Failure Modes The list of ways this stops working, in rough order of frequency: * **No listing-page polish.** Default placeholder image, two-sentence description, no use cases. Buyers bounce in 4 seconds. * **Mispriced.** Either listed as free (no one signals value with \$0) or listed at \$499/mo with no track record. Anchor at \$19–49 and raise after you have testimonials. * **No demo video or public demo.** Buyers can't imagine the agent running on their data. They don't buy. * **No public examples.** No tweets, no thread, no screenshots in the wild. Discovery has nothing to grip onto. * **Promoting on the wrong subreddits.** Generic AI subreddits drown signal in noise. Find the three subreddits where the *buyer* hangs out, not the three where other builders hang out. * **Building the agent for everyone.** "AI assistant for productivity" never sells. "Cleans messy financial CSVs in 30 seconds" sells. * **Treating tokenization as a side experiment.** It's a second revenue stream. Claim fees weekly, post the lifetime totals, and let the on-chain proof do its own marketing. *** ## Next Steps * [Launchpad: Tokenize Your Agent Tutorial](/docs/marketplace/launchpad-tokenize-your-agent-tutorial) — the four-step Launchpad walkthrough referenced in Step 4. * [Agents API](/docs/marketplace/agents-api) — full reference for create, edit, and query endpoints. * [Tokenization Details](/docs/marketplace/tokenization_details) — how the bonding curve, fees, and migration work under the hood. * [Marketplace Publishing Quickstart](/docs/marketplace/marketplace_publishing_quickstart) — the SDK-side `publish_to_marketplace=True` flow if you'd rather publish from inside your `Agent` definition. * [Monetization Guide](/docs/marketplace/monetize) — eligibility, pricing tiers, and platform-fee math. * [Claim Fees API](/docs/marketplace/claim-fees-api) — the endpoint behind Step 6, with retry and async patterns. # Night-Mode Pricing: 50% Off Overnight Batch Workflows Source: https://docs.swarms.ai/docs/guides/guides/night-mode-pricing-strategy Move batch swarms and overnight pipelines into the 8 PM – 6 AM Pacific window for a 50% discount on swarm-completion token costs. Includes scheduling recipes with cron and Airflow. ## What This Covers * The exact window the discount applies to (8 PM – 6 AM **America/Los\_Angeles**) and what it covers * Realistic monthly savings: a team running 1,000 swarm jobs/day at daytime rates vs. overnight rates * A drop-in cron recipe for scheduling overnight batch swarms from any server * An Airflow DAG pattern for production-grade overnight orchestration * The two failure modes to watch: timezone drift and on-the-boundary jobs ## Why This Matters The single highest-ROI cost lever the Swarms API offers is its overnight discount: **swarm-completion input and output tokens are billed at 50% between 8 PM and 6 AM Pacific time**. For any workload that doesn't need sub-second turnaround — overnight reports, daily research digests, RAG-index refreshes, training-data generation, backfills, evaluation suites — this is free money you collect by changing *when* the job runs, not *what* the job runs. A team spending \$10,000/month on swarm jobs that could shift to the overnight window saves roughly **\$4,500/month** with zero code-quality tradeoff. This guide makes that shift mechanical. ## How the Discount Works The discount is applied server-side, in `api/swarm_completions.py`, inside the `calculate_swarm_cost` function. When a swarm completion finishes, the billing function checks the current hour in `America/Los_Angeles`: ```python theme={null} # Excerpt from api/swarm_completions.py — the billing path california_tz = pytz.timezone("America/Los_Angeles") current_time = datetime.now(california_tz) is_night_time = current_time.hour >= 20 or current_time.hour < 6 # 8 PM to 6 AM if is_night_time: input_token_cost *= pricing.night_time_discount # 0.50 = 50% off output_token_cost *= pricing.night_time_discount # 0.50 = 50% off ``` **What's discounted:** * `swarm_completions_input_cost_per_1m` — full 50% off * `swarm_completions_output_cost_per_1m` — full 50% off **What's NOT discounted:** * `swarm_completions_agent_cost` — the `$0.01` per-agent fee is billed full price For most production workloads the per-agent fee is a rounding error, but for high-fan-out heavy swarms with 20+ agents per job, it stays linear. Your savings ceiling on token costs is exactly 50%; agent-fee savings are 0%. <Info> The check is on **the time the run finishes**, in Pacific. A job that starts at 5:55 AM and finishes at 6:02 AM PT will be billed at the **daytime** rate. Schedule batches to land cleanly inside the window — see "Scheduling on the Boundary" below. </Info> ## The Monthly Math Take a realistic mid-sized team: 1,000 swarm jobs per day, each averaging: * 5 agents * 6,000 input tokens * 3,000 output tokens ### Daytime baseline (jobs run during business hours) Per-job cost: ``` input_cost = (6_000 / 1_000_000) * 6.50 = $0.0390 output_cost = (3_000 / 1_000_000) * 18.50 = $0.0555 agent_cost = 5 * 0.01 = $0.0500 total/run = $0.1445 ``` Per day: `$0.1445 * 1,000 = $144.50` Per 30-day month: **\$4,335.00** ### Overnight: same workload, scheduled 8 PM – 6 AM PT Per-job cost: ``` input_cost = $0.0390 * 0.50 = $0.0195 output_cost = $0.0555 * 0.50 = $0.02775 agent_cost = $0.0500 (NOT discounted) total/run = $0.09725 ``` Per day: `$0.09725 * 1,000 = $97.25` Per 30-day month: **\$2,917.50** ### Savings **\$4,335 – \$2,917.50 = \$1,417.50/month** saved by shifting the same workload into the overnight window. Annualized: **\$17,010**. Zero code changes to the agents themselves — just *when* they run. For larger workloads the savings scale linearly until the agent-fee floor dominates. At 10,000 jobs/day this same calculation yields **\$14,175/month** in savings. ## Verifying the Discount in Your Response Every swarm completion response includes a `discount_active` flag. Check it programmatically to confirm your scheduling actually landed in the window: ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } resp = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={ "name": "Nightly Research Digest", "swarm_type": "SequentialWorkflow", "task": "Summarize today's developments in AI infrastructure.", "agents": [ {"agent_name": "Scanner", "model_name": "gpt-4.1-mini", "max_tokens": 1024}, {"agent_name": "Synthesizer", "model_name": "gpt-4.1", "max_tokens": 2048}, ], }, ) billing = resp.json()["usage"]["billing_info"] print(f"Discount active: {billing['discount_active']}") print(f"Discount type: {billing['discount_type']}") print(f"Discount percent: {billing['discount_percentage']}%") print(f"Total cost (USD): ${billing['total_cost']}") ``` If `discount_active` is `False` on a job you scheduled for overnight, your cron or worker timezone is wrong — see the troubleshooting section below. *** ## Scheduling Recipe 1: System cron The simplest possible setup. Add this to your crontab and you're done. Note that **cron schedules are interpreted in the system's local time** — be deliberate about which timezone your server runs in. ```bash theme={null} # /etc/crontab — assumes the host is set to America/Los_Angeles # Run the nightly batch at 9:00 PM Pacific, safely inside the discount window 0 21 * * * /usr/bin/python3 /opt/jobs/run_nightly_batch.py >> /var/log/nightly.log 2>&1 ``` If your server runs in UTC (common on cloud VMs), convert explicitly: ```bash theme={null} # UTC server: 9 PM PT = 04:00 UTC (PST) / 03:00 UTC (PDT). Pick one and stick to it, # OR use the more robust env-based form below: CRON_TZ=America/Los_Angeles 0 21 * * * /usr/bin/python3 /opt/jobs/run_nightly_batch.py >> /var/log/nightly.log 2>&1 ``` `CRON_TZ` is supported by Vixie cron and systemd timers — it makes your schedule survive DST shifts without manual adjustment. The batch script itself is the same swarm call you'd write at any other time. The discount is applied server-side based on when the request hits the API, not on any flag you set. ```python theme={null} # /opt/jobs/run_nightly_batch.py import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # A batch of overnight reports — each one independently swarmed. JOBS = [ {"name": "EU Market Digest", "task": "Summarize today's EU SaaS funding announcements."}, {"name": "US Macro Digest", "task": "Summarize today's US macro data releases."}, {"name": "Crypto Flow Digest", "task": "Summarize today's notable on-chain flows."}, ] AGENT_SPECS = [ {"agent_name": "Scanner", "model_name": "gpt-4.1-mini", "max_tokens": 1024}, {"agent_name": "Synthesizer", "model_name": "gpt-4.1", "max_tokens": 2048}, ] for job in JOBS: resp = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json={ "name": job["name"], "swarm_type": "SequentialWorkflow", "task": job["task"], "agents": AGENT_SPECS, }, timeout=300, ) billing = resp.json()["usage"]["billing_info"] print(f"[{job['name']}] discount_active={billing['discount_active']} total=${billing['total_cost']}") ``` *** ## Scheduling Recipe 2: Airflow DAG For teams already running Airflow, this is the production-grade pattern. The DAG runs once per night at 9 PM PT, fans out to N batch jobs in parallel via `batch_swarm_completions`, and writes a cost-discount audit so you can prove the 50% landed. ```python theme={null} # dags/nightly_swarm_batch.py from __future__ import annotations import os import pendulum import requests from airflow.decorators import dag, task API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"} JOBS = [ {"name": "EU Market Digest", "task": "Summarize today's EU SaaS funding announcements."}, {"name": "US Macro Digest", "task": "Summarize today's US macro data releases."}, {"name": "Crypto Flow Digest", "task": "Summarize today's notable on-chain flows."}, ] AGENT_SPECS = [ {"agent_name": "Scanner", "model_name": "gpt-4.1-mini", "max_tokens": 1024}, {"agent_name": "Synthesizer", "model_name": "gpt-4.1", "max_tokens": 2048}, ] @dag( dag_id="nightly_swarm_batch", schedule="0 21 * * *", # 9 PM in the DAG's TZ start_date=pendulum.datetime(2025, 1, 1, tz="America/Los_Angeles"), catchup=False, tags=["swarms", "overnight", "discount"], ) def nightly_swarm_batch(): @task def submit_batch(): """Send all jobs in a single batch request — one round trip, Swarms parallelises server-side.""" payload = [ { "name": job["name"], "swarm_type": "SequentialWorkflow", "task": job["task"], "agents": AGENT_SPECS, } for job in JOBS ] resp = requests.post( f"{BASE_URL}/v1/swarm/batch/completions", headers=HEADERS, json=payload, timeout=600, ) resp.raise_for_status() return resp.json() @task def audit_discount(batch_result: list): """Fail the DAG run loudly if the discount didn't land — catches misconfigured schedulers before they cost you a month of full-price runs.""" failures = [] for item in batch_result: usage = item.get("usage", {}) billing = usage.get("billing_info", {}) if not billing.get("discount_active"): failures.append(item.get("swarm_name", "<unnamed>")) if failures: raise RuntimeError( f"Overnight discount did not apply to: {failures}. " f"Check scheduler timezone (must run between 8 PM and 6 AM Pacific)." ) return f"OK — all {len(batch_result)} runs got the 50% discount." audit_discount(submit_batch()) nightly_swarm_batch() ``` The `audit_discount` task is the bit most teams forget. Without it, a daylight-savings change or a quiet timezone reconfiguration can move your overnight job back into the daytime band and you won't notice until the invoice arrives. *** ## Scheduling on the Boundary The discount window is `hour >= 20 or hour < 6` in Pacific. Two practical implications: 1. **5:59 AM PT is still discounted; 6:00 AM PT is not.** If your job is long-running, start it earlier so it finishes inside the window. 2. **8:00 PM PT is the earliest discounted moment.** A job that starts at 7:55 PM lands at the full-price rate. Give yourself a buffer. Schedule starts at **9 PM PT** (one hour past the boundary) and target completion **by 5 AM PT** (one hour before the boundary closes). That gives you eight clean hours of discount and protects against DST-driven hour shifts. ```python theme={null} # Pre-flight check: refuse to submit if we're inside the boundary buffer from datetime import datetime import pytz def in_discount_window(buffer_minutes: int = 15) -> bool: """True iff we're at least `buffer_minutes` inside the 8 PM – 6 AM PT window.""" pt = pytz.timezone("America/Los_Angeles") now = datetime.now(pt) minute_of_day = now.hour * 60 + now.minute window_start = 20 * 60 + buffer_minutes # 8:15 PM window_end = 6 * 60 - buffer_minutes # 5:45 AM return minute_of_day >= window_start or minute_of_day < window_end if not in_discount_window(): raise SystemExit("Not safely inside the discount window — aborting overnight batch.") ``` *** ## Troubleshooting | Symptom | Cause | Fix | | --------------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `discount_active: false` on a job you scheduled overnight | Scheduler ran in UTC/local-server-time, not Pacific | Set `CRON_TZ=America/Los_Angeles` or convert in your DAG | | Discount lands on some runs in the batch but not others | Long-running job crossed the 6 AM boundary | Start earlier; cap batch size so all runs finish before 5 AM PT | | Discount applied but bill barely changed | Agent fee dominates (heavy-swarm pattern with many agents) | Token costs are 50% off; the `$0.01 * num_agents` fee is not. Prune agents per the [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) | | Daylight savings broke the schedule | Cron is using a fixed UTC offset that no longer matches PT | Use `CRON_TZ=America/Los_Angeles` (or Airflow's `tz=...`) — these handle DST | ## When NOT to Use Night Mode Night-mode is a batch-economics play. Don't shoehorn the following into the overnight window — the user-experience cost outweighs the discount: * Interactive chat or assistant traffic — users want answers now * Webhook-driven agent runs where the upstream caller is blocking * Realtime fraud / moderation / classification pipelines * Anything where a 6-hour latency would break a contract Use it for everything else: backfills, analyst digests, RAG-index refreshes, evaluation suites, content pre-generation, model-comparison sweeps, and bulk research jobs. ## Next Steps * [Batch Swarm Scale Tutorial](/docs/examples/examples/batch-swarm-scale-tutorial) — full batch-swarm scaling patterns to pair with night-mode * [Batch Agent Scale Tutorial](/docs/examples/examples/batch-agent-scale-tutorial) — batching individual agent completions * [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) — pair night-mode with a tiered architecture for compounding savings # Drop-In Migration from OpenAI SDK to Swarms Source: https://docs.swarms.ai/docs/guides/guides/openai-sdk-drop-in You already have an OpenAI client. Change a base_url and you get multi-agent for free — then upgrade to /v1/swarm/completions when you want full orchestration. A strategic migration narrative. ## What This Covers * The two-line migration: pointing your existing `openai` Python client at Swarms with no other code changes * Why bearer-token auth works the same as `x-api-key` — your existing OpenAI auth pattern transfers * The optional upgrade path: when to graduate from `/v1/chat/completions` (single model) to `/v1/swarm/completions` (multi-agent swarm) * Realistic before/after architecture for an existing OpenAI-backed app * What you don't have to throw away — streaming, history, vision, retries ## Why This Matters Most teams already have an `openai` client wired into production. Logging, retries, observability, prompt versioning, evaluation — all of it sits behind that one SDK call. The switching cost of "rewrite to a new SDK" is what keeps teams locked into single-model architectures even when their problems demand a swarm. The Swarms API removes that cost: it speaks the OpenAI ChatCompletion protocol on `/v1/chat/completions` and accepts either `x-api-key` or `Authorization: Bearer <key>` — meaning your existing OpenAI SDK code becomes a Swarms client by changing **two strings**. From there, you can graduate one endpoint at a time to multi-agent without rewriting the layers around it. This guide is the migration narrative, not a feature tour. For the feature tour, see [OpenAI-Compatible Chat Completions](/docs/examples/examples/openai-compatible). ## The Two-Line Migration Here is the code you already have: <Tabs> <Tab title="Before — vanilla OpenAI"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["OPENAI_API_KEY"], ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a senior financial analyst."}, {"role": "user", "content": "What are the top risks in EM bonds right now?"}, ], max_tokens=512, temperature=0.3, ) print(response.choices[0].message.content) ``` </Tab> <Tab title="After — pointing at Swarms"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", # <-- the only structural change ) response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a senior financial analyst."}, {"role": "user", "content": "What are the top risks in EM bonds right now?"}, ], max_tokens=512, temperature=0.3, ) print(response.choices[0].message.content) ``` </Tab> </Tabs> That's the entire migration for the basic case. The request shape, response shape, streaming protocol, error classes, and SDK methods are identical. Your retry middleware, your prompt-template layer, your token-counting telemetry — none of it has to change. ## Authentication: Bearer Token Works Too The OpenAI SDK injects `Authorization: Bearer <key>` automatically. Swarms accepts both that header and the `x-api-key` header that the rest of the Swarms docs reference — they're equivalent, and the platform falls back from one to the other server-side. This means: * Your **OpenAI SDK code** keeps using `Authorization: Bearer` (transparently — you don't see it) * Your **`requests`-style code** can keep using `x-api-key` (matches every other guide) * Mixed codebases work without translating between auth schemes ```python theme={null} # Both of these authenticate the same request to Swarms. # Style 1: OpenAI SDK (uses Authorization: Bearer under the hood) client = OpenAI(api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1") # Style 2: raw requests with x-api-key headers = {"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"} # Style 3: raw requests with bearer — also accepted headers_bearer = {"Authorization": f"Bearer {os.environ['SWARMS_API_KEY']}", "Content-Type": "application/json"} ``` If your existing OpenAI integration uses bearer tokens because that's what the SDK does, you don't have to change anything. If you're hand-rolling HTTP calls and want to match the Swarms doc convention, use `x-api-key`. Either is fine. ## What You Keep For Free The Swarms `/v1/chat/completions` endpoint is a faithful OpenAI ChatCompletion. The following continue to work, unmodified, after the base-url swap: * **Streaming** (`stream=True` — token-by-token deltas) * **System / user / assistant messages**, including full multi-turn history * **Vision / image input** via the multimodal `content` array * **Standard error classes** from the SDK (`openai.RateLimitError`, `openai.APIStatusError`, etc.) * **`usage` accounting** in the response — prompt/completion/total token counts * **`max_tokens`, `temperature`, `top_p`, `presence_penalty`, `frequency_penalty`** all forwarded A worked example reusing the SDK exactly as you'd use it against OpenAI: ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) # Streaming, multi-turn, vision, error-handling — all unchanged from OpenAI. stream = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a meticulous code reviewer."}, {"role": "user", "content": "Review this function for edge cases: def divide(a, b): return a / b"}, ], stream=True, max_tokens=1024, ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True) ``` ## The First Free Upgrade: `max_loops` The Swarms endpoint adds **one** non-OpenAI parameter you can pass through `extra_body`: `max_loops`. It tells the agent to iterate on its own output — think "self-review and refine" without you writing the orchestration. This is the first piece of multi-agent thinking you can adopt without leaving the `chat.completions` shape. ```python theme={null} response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "Write a solution, then critique it, then output the corrected version."}, {"role": "user", "content": "Implement longest_palindromic_substring(s: str) -> str."}, ], max_tokens=2048, extra_body={"max_loops": 3}, # <-- self-iterate three times before returning ) ``` `max_loops` defaults to `1` (single pass — identical to OpenAI behavior). Bumping it to 2 or 3 is often the cheapest quality win on hard reasoning tasks. For the full reference see [OpenAI-Compatible Chat Completions](/docs/examples/examples/openai-compatible). *** ## The Strategic Upgrade: `/v1/swarm/completions` The `chat.completions` shape is a single conversation with a single agent. That's the right tool for many calls, but the reason teams come to Swarms is that some calls need to be **a coordinated team of specialised agents** — a researcher, an analyst, a critic, a synthesizer. The OpenAI protocol doesn't have a vocabulary for that. Swarms does, on its native `/v1/swarm/completions` endpoint. The decision is per-endpoint: keep using `chat.completions` for chat-shaped calls, and route the calls that need orchestration to `swarm/completions`. You don't migrate everything at once. ### When to upgrade an endpoint Upgrade to `/v1/swarm/completions` when any of these are true: * The prompt has more than one *role* baked into it (e.g. "first research X, then critique it, then summarise") * You're already doing your own agent orchestration in application code (function-calling loops, sub-agent dispatch) * The output quality is bottlenecked on a single model trying to do too much in one pass * You need parallel work — concurrent research across multiple angles — combined into one answer ### Side-by-side: the same job, two endpoints <Tabs> <Tab title="OpenAI-compatible (single agent)"> ```python theme={null} import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI( api_key=os.environ["SWARMS_API_KEY"], base_url="https://api.swarms.world/v1", ) # One model, one pass. Cheap, fast, fine for simple analysis. response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "You are a strategy analyst. Research, analyse, and recommend."}, {"role": "user", "content": "Should a Series-B SaaS company enter the German market?"}, ], max_tokens=2048, extra_body={"max_loops": 2}, # self-iterate once for quality ) print(response.choices[0].message.content) ``` </Tab> <Tab title="Swarm-native (multi-agent)"> ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.environ["SWARMS_API_KEY"] BASE_URL = "https://api.swarms.world" # x-api-key OR Authorization: Bearer — pick whichever matches your stack headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} # Four specialist agents, one synthesizer, run as a sequential workflow. # Each agent is cheaper and tighter than the single generalist above — # the synthesizer is where you spend the token budget. payload = { "name": "German Market Entry Analysis", "swarm_type": "SequentialWorkflow", "task": "Should a Series-B SaaS company enter the German market?", "agents": [ { "agent_name": "Market Researcher", "system_prompt": "Surface 3 key facts about the German SaaS market.", "model_name": "gpt-4.1-mini", "max_tokens": 768, }, { "agent_name": "Competitive Analyst", "system_prompt": "Identify the top 3 incumbents and their moats.", "model_name": "gpt-4.1-mini", "max_tokens": 768, }, { "agent_name": "Risk Analyst", "system_prompt": "List the top 3 entry risks and mitigations.", "model_name": "gpt-4.1-mini", "max_tokens": 768, }, { "agent_name": "Director (Synthesizer)", "system_prompt": "Read the three briefings. Produce a go/no-go memo.", "model_name": "gpt-4.1", "max_tokens": 3072, }, ], } resp = requests.post(f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload) print(resp.json()["output"]) ``` </Tab> </Tabs> The point is **you can keep the left-hand call exactly where it is** while introducing the right-hand call for the analyses that actually need multi-agent reasoning. The two endpoints live side-by-side in the same app, behind the same API key. *** ## A Migration Plan You Can Actually Run A pragmatic week-one migration for a team currently on OpenAI: 1. **Day 1.** Add a `SWARMS_API_KEY` to your secrets. Duplicate your OpenAI client construction into a `swarms_client` that differs only in `api_key` and `base_url`. Ship to staging behind a feature flag. 2. **Day 2.** Move your *least-critical* chat.completions endpoint to `swarms_client`. Confirm logs, retries, token counting, and streaming all behave. Diff the response on a few hundred prompts against the OpenAI baseline. 3. **Day 3.** Identify the **one** endpoint in your product that does the most prompt engineering — the long, multi-section system prompt with "first do X, then Y, then Z". This is the one that wants to be a swarm. Cut it over to `/v1/swarm/completions` with 3–5 agents. 4. **Day 4.** Add the [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) patterns to that swarm — tier the workers, compress the handoffs. 5. **Day 5.** Schedule the batch / overnight pieces of your pipeline against the [Night-Mode discount](/docs/guides/guides/night-mode-pricing-strategy). Audit `discount_active` to confirm. After that, the rest is per-endpoint at your pace. You don't have to migrate everything to claim the wins. ## What You Don't Have To Throw Away * Your OpenAI SDK and any wrappers around it * Your retry / circuit-breaker middleware * Your token-counting and cost-tracking telemetry * Your prompt-versioning system * Your evaluation harness (the response shape is identical) * Your streaming UI code * Your `Authorization: Bearer` auth flow What you gain is an upgrade path that doesn't require a rewrite to take — you adopt multi-agent endpoint-by-endpoint, paying only for the ones that actually need it. ## Next Steps * [OpenAI-Compatible Chat Completions](/docs/examples/examples/openai-compatible) — full feature reference for the drop-in endpoint (streaming, vision, multi-turn, multi-loop) with TypeScript, Go, and Rust examples * [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) — once you're on `/v1/swarm/completions`, this is the architecture that gets your bill down * [Night-Mode Pricing Strategy](/docs/guides/guides/night-mode-pricing-strategy) — 50% off tokens 8 PM – 6 AM Pacific, schedule your batches accordingly # Production Observability with Swarms Source: https://docs.swarms.ai/docs/guides/guides/production-observability Wire /v1/account/logs, /v1/usage/costs, /v1/account/credits, and X-RateLimit-* headers into a single operator dashboard for cost, error, and quota visibility. ## What This Covers * How the four observability signals fit together: per-request logs, daily usage rollup, credit balance, and live rate-limit headers * A small Python script that pulls the last 24 hours of activity, aggregates by `swarm_type`, and prints a cost-and-error breakdown * The audit-trail story for enterprise, healthcare, finance, and other regulated workloads * Which signal answers which operational question — and which one you should be pulling first ## Why This Matters Most teams discover their observability gap the day a customer asks "what did the agent see on Tuesday at 2pm and how much did it cost us?" The Swarms API exposes everything you need to answer that — but the data is split across four endpoints with different shapes, time grains, and refresh cadences. This guide is the operator narrative on top of the [Swarm Logs](/docs/examples/examples/swarm-logs), [Usage Report](/docs/examples/examples/usage-report), and [Account Credits](/docs/examples/examples/account-credits) reference pages: which signal to use when, how to combine them, and the minimum production-grade script for a daily dashboard. ## The Four Signals | Signal | Endpoint / Source | Time grain | Answers | | ------------------ | --------------------------------- | ---------------------------- | ---------------------------------------------------------- | | Per-request logs | `GET /v1/account/logs` | Per request | "What ran? Did it succeed? How much did it cost?" | | Live pricing rates | `GET /v1/usage/costs` | Snapshot (current rate card) | "What are we billed per token / agent / search right now?" | | Credit balance | `GET /v1/account/credits` | Snapshot | "Do we have headroom for the next batch job?" | | Rate-limit headers | `X-RateLimit-*` on every response | Per request | "Are we about to get 429'd? Do we need to back off?" | The rule of thumb: **headers for the next millisecond, logs for the last hour (and for trend analysis — there's no separate daily-rollup endpoint), live rates before you estimate a job's cost, credits before you submit a batch.** ## Step 1: Configure the Client ```python theme={null} import os from collections import Counter, defaultdict from datetime import datetime, timedelta, timezone import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} ``` ## Step 2: Pull Last-24h Logs, Aggregated by Swarm Type The single most useful operator script: what ran in the last 24 hours, grouped by `swarm_type`, with cost and error counts per group. ```python theme={null} def fetch_logs(): resp = requests.get(f"{BASE_URL}/v1/account/logs", headers=headers, timeout=30) resp.raise_for_status() return resp.json() def last_24h_breakdown(): data = fetch_logs() cutoff = datetime.now(timezone.utc) - timedelta(hours=24) by_type = defaultdict(lambda: {"count": 0, "errors": 0, "cost": 0.0, "tokens": 0}) untyped = {"count": 0, "errors": 0, "cost": 0.0, "tokens": 0} for log in data.get("logs", []): ts_raw = log.get("timestamp") if not ts_raw: continue ts = datetime.fromisoformat(ts_raw.replace("Z", "+00:00")) if ts < cutoff: continue # swarm_type lives inside the request payload echoed in the log swarm_type = ( log.get("data", {}).get("swarm_type") or log.get("swarm_type") or None ) bucket = by_type[swarm_type] if swarm_type else untyped bucket["count"] += 1 bucket["cost"] += float(log.get("cost", 0) or 0) bucket["tokens"] += int(log.get("tokens_used", 0) or 0) if (log.get("status_code") or 200) >= 400: bucket["errors"] += 1 print("Last 24 hours, by swarm_type") print("-" * 70) print(f"{'swarm_type':<22} {'reqs':>6} {'errs':>6} {'tokens':>10} {'cost':>10}") print("-" * 70) for swarm_type, b in sorted(by_type.items(), key=lambda kv: kv[1]["cost"], reverse=True): print( f"{(swarm_type or '-'):<22} " f"{b['count']:>6} {b['errors']:>6} " f"{b['tokens']:>10,} ${b['cost']:>8.4f}" ) if untyped["count"]: print( f"{'(single-agent)':<22} " f"{untyped['count']:>6} {untyped['errors']:>6} " f"{untyped['tokens']:>10,} ${untyped['cost']:>8.4f}" ) total_cost = sum(b["cost"] for b in by_type.values()) + untyped["cost"] total_err = sum(b["errors"] for b in by_type.values()) + untyped["errors"] total_req = sum(b["count"] for b in by_type.values()) + untyped["count"] print("-" * 70) print(f"Total: {total_req} requests, {total_err} errors, ${total_cost:.4f}") if __name__ == "__main__": last_24h_breakdown() ``` <Note> The exact shape of each log entry can vary slightly — `swarm_type`, `agent_name`, and `model_name` may appear at the top level or nested under `data`. The code above is defensive against both. See the [Swarm Logs reference](/docs/examples/examples/swarm-logs) for the full schema. </Note> ## Step 3: Reconcile Logged Costs Against Live Pricing `/v1/usage/costs` is not a historical rollup — it returns the current rate card (`usage_pricing`) the platform is billing right now, plus a timestamp. There's no per-day or per-period usage-history endpoint in the API; `/v1/account/logs` is the only durable, per-request record of what you actually spent. Use the live rate card to sanity-check that the costs your logs recorded still match the rates you expect — this catches a pricing change you didn't notice, or a client-side cost estimate that's gone stale. ```python theme={null} def fetch_current_pricing() -> dict: resp = requests.get(f"{BASE_URL}/v1/usage/costs", headers=headers, timeout=30) resp.raise_for_status() return resp.json()["usage_pricing"] def reconcile_today(): today = datetime.now(timezone.utc).strftime("%Y-%m-%d") # Logs side: sum all of today's entries (the only durable record of spend) logs = fetch_logs().get("logs", []) logs_cost = sum( float(log.get("cost", 0) or 0) for log in logs if (log.get("timestamp") or "").startswith(today) ) # Rates side: pull the live pricing rate card pricing = fetch_current_pricing() print(f"Logs total ({today}): ${logs_cost:.4f}") print(f"Swarm input rate (live): ${pricing['swarm_completions_input_cost_per_1m']}/1M tokens") print(f"Swarm output rate (live): ${pricing['swarm_completions_output_cost_per_1m']}/1M tokens") print(f"Per-agent rate (live): ${pricing['swarm_completions_agent_cost']}/agent") print( "Sanity-check: if the per-request costs in your logs don't line up " "with what these rates would produce, either the rate card changed " "mid-day or your client-side cost estimate is stale." ) ``` ## Step 4: Check Credits Before a Batch Job The cheapest production incident to avoid is "the batch job stopped halfway because credits ran out." One call before the submit loop is enough. ```python theme={null} def credits_remaining() -> float: resp = requests.get(f"{BASE_URL}/v1/account/credits", headers=headers, timeout=10) resp.raise_for_status() return float(resp.json().get("total_credits", 0)) def guard_batch(estimated_cost: float, safety_margin: float = 1.5): """Refuse to start a batch if credits < estimated_cost * safety_margin.""" available = credits_remaining() required = estimated_cost * safety_margin if available < required: raise RuntimeError( f"Insufficient credits: have ${available:.2f}, " f"need ${required:.2f} (estimated ${estimated_cost:.2f} x {safety_margin})." ) print(f"Credit check OK: ${available:.2f} available, ${required:.2f} required.") ``` ## Step 5: Watch Rate-Limit Headers in Flight The headers are on **every** authenticated response, including errors. You do not need a separate call. Log them after every request and feed the data into your throttling logic. ```python theme={null} def call_with_headers_logged(payload: dict): resp = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=600, ) rl = {k: v for k, v in resp.headers.items() if k.lower().startswith("x-ratelimit")} print( f"tier={rl.get('X-RateLimit-Tier')} " f"min={rl.get('X-RateLimit-Remaining-Minute')}/{rl.get('X-RateLimit-Limit-Minute')} " f"day={rl.get('X-RateLimit-Remaining-Day')}/{rl.get('X-RateLimit-Limit-Day')}" ) if resp.status_code == 429: retry_after = int(resp.headers.get("Retry-After", "60")) print(f"Rate limited. Retry after {retry_after}s.") return None resp.raise_for_status() return resp.json() ``` See the [Rate Limit Headers reference](/docs/documentation/resources/rate-limit-headers) for the full header schema and tier thresholds. ## The Audit-Trail Value For enterprise and regulated workloads — healthcare, financial services, legal, defense — the per-request log is not a nice-to-have. It's the artifact your compliance team needs to answer post-hoc questions like: * "Show every agent invocation that touched patient X's data between March 1 and March 15." * "Reconstruct the chain of agent outputs that produced this trade recommendation." * "Produce the model name, system prompt, and output for the decision made at 14:32 UTC." The `/v1/account/logs` endpoint is filtered to your API key and excludes client IP addresses for privacy, but otherwise retains the request shape, the model invoked, the response time, and the cost. Combined with deterministic agent configs (low temperature, pinned model names, fixed `max_loops`), it gives you a reproducible record per agent call — which is what most regulators actually want. <Info> The platform's existing log retention is suitable for debugging and operational analytics. For workloads with formal retention requirements (GxP, HIPAA, SOX, SR 11-7), export logs to your own storage on a daily cadence — the [Swarm Logs examples](/docs/examples/examples/swarm-logs) show CSV/JSON/compressed export patterns. </Info> ## Putting It Together: Daily Operator Cron A pragmatic daily cron looks like this: 1. **00:05 UTC** — pull `/v1/usage/costs` to snapshot the current rate card; diff it against yesterday's snapshot to catch pricing changes 2. **00:10 UTC** — pull `/v1/account/logs`; archive yesterday's entries to S3 / your log lake; aggregate by `swarm_type` and `model_name` for finance — this log aggregation is also where your daily total cost comes from, since there's no separate daily-rollup endpoint 3. **00:15 UTC** — pull `/v1/account/credits`; alert if `total_credits < daily_budget * 7` 4. **Continuously** — every production request logs its `X-RateLimit-Remaining-Minute`; alert if a rolling 5-minute average drops below 20% of `X-RateLimit-Limit-Minute` That's the full observability story — three scheduled pulls and one inline log line per request. ## Next Steps * Read [Swarm Logs & API History](/docs/examples/examples/swarm-logs) for filtering, export, and the full log schema * Read [Usage Report](/docs/examples/examples/usage-report) for daily-rollup query parameters and the response schema * Read [Rate Limit Headers](/docs/documentation/resources/rate-limit-headers) for tier thresholds and the full header set * Read the [Production Readiness Checklist](/docs/guides/guides/production-readiness-checklist) to wire these signals into a complete production wrapper # Production Readiness Checklist Source: https://docs.swarms.ai/docs/guides/guides/production-readiness-checklist The terse, opinionated checklist for shipping the Swarms API to production: rate limits, idempotency, retries, error handling, cost monitoring, batch endpoints, and a copy-paste wrapper that does all of it. ## What This Covers * The non-negotiables before you put the Swarms API on the critical path of a production system * Rate-limit, retry, idempotency, and error-handling defaults that match how the API actually behaves * A single Python wrapper that bundles retry-with-backoff, a budget cap, and post-run log verification * The right endpoints to use for offline / batch workloads * When to upgrade to the premium tier ## Why This Matters The first 80% of any API integration is happy-path code. The last 20% — the part that decides whether you get paged at 3am — is rate-limit handling, retries on transient failures, budget guardrails, and an audit trail. This guide is the terse checklist for that last 20%, written for SREs and senior engineers who already know what exponential backoff is and just want the production-correct defaults for this specific API. ## The Checklist ### Rate Limits * [ ] Read the `X-RateLimit-Remaining-Minute` and `X-RateLimit-Remaining-Day` headers on **every** response and log them * [ ] On `429`, honor the `Retry-After` header verbatim — don't substitute your own value * [ ] Throttle proactively when `Remaining-Minute / Limit-Minute < 0.1` rather than waiting for the 429 * [ ] If you're hitting limits regularly, upgrade to premium (2,000/min, 100,000/day) before re-engineering * [ ] Reference: [Rate Limit Headers](/docs/documentation/resources/rate-limit-headers), [Rate Limits](/docs/documentation/resources/ratelimits) ### Idempotency and Request IDs * [ ] Generate a client-side request ID (UUID v4) for every submit and persist it alongside the payload * [ ] Use the request ID as the join key when you later reconcile against `/v1/account/logs` * [ ] Treat retries as idempotent only if you've established the original request never succeeded — a 5xx or a timeout is not proof of non-execution ### Retry Policy * [ ] Retry on `5xx`, connection errors, and read timeouts. **Never** retry on `4xx` other than `429` * [ ] Use exponential backoff with full jitter: `sleep = random.uniform(0, base * 2**attempt)` * [ ] Cap at 4–5 attempts. Beyond that, the underlying issue isn't transient * [ ] On `429`, use `Retry-After` instead of your computed backoff ### Structured Error Handling * [ ] Always check `response.status_code` and raise on non-2xx — do not blindly `response.json()` * [ ] Capture the request ID, `X-RateLimit-*` headers, status code, response body, and elapsed time on every error * [ ] Distinguish "API rejected the request" (4xx) from "API never saw it" (network) — they require different remediation * [ ] Log the failed payload's `swarm_type` and per-agent `model_name` for debugging ### Cost Monitoring * [ ] Before any batch run, call `/v1/account/credits` and refuse to submit if `total_credits < estimated_cost * 1.5` * [ ] After every run, persist `result["usage"]["billing_info"]["total_cost"]` to your warehouse keyed by request ID * [ ] Run a daily cron against `/v1/usage/costs` and alert on day-over-day cost > 2x the trailing 7-day mean * [ ] Set hard budget caps in your wrapper — a runaway loop should fail fast, not bleed credits * [ ] Reference: [Production Observability](/docs/guides/guides/production-observability), [Usage Report](/docs/examples/examples/usage-report), [Get Credit Balance](/docs/examples/examples/account-credits) ### Batch Endpoints for Offline Workloads * [ ] If you're submitting more than \~20 requests in a tight loop, switch to the batch endpoints * [ ] Use batch for backfills, evaluation sweeps, nightly report generation — anything where latency-per-row is not the goal * [ ] References: [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions), [Batch Processing](/docs/examples/examples/batch-processing) ### Premium Tier Thresholds Upgrade to premium when **any** of these are true. The premium tier is \$100/month and gives you 20x the per-minute, 29x the per-hour, and 83x the per-day quota — and 10x the per-agent token budget. * [ ] You hit a `429` more than once per day in production * [ ] You need to run more than 1,200 requests per day * [ ] Any single agent needs `max_tokens > 200,000` * [ ] Reference: [Premium Endpoints](/docs/documentation/resources/premium-endpoints) ### Audit and Compliance * [ ] Daily export of `/v1/account/logs` to your own log lake (S3, BigQuery, etc.) * [ ] Pin `model_name` per agent. Do not let your code "pick a model" at runtime in regulated workloads * [ ] For regulated workloads, set `temperature=0` (or omit it on Opus 4.8) and `max_loops=1` for reproducibility ## The Wrapper One file. Drop it in. It does retry-with-backoff that honors `Retry-After`, a hard budget cap, request-ID tagging, and post-run log verification. ```python theme={null} import logging import os import random import time import uuid from dataclasses import dataclass from typing import Any, Optional import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" HEADERS = {"x-api-key": API_KEY, "Content-Type": "application/json"} log = logging.getLogger("swarms.prod") logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") @dataclass class RunResult: request_id: str ok: bool status_code: int cost: float elapsed: float body: Any rate_limit: dict class BudgetExceeded(RuntimeError): pass class ProductionClient: """Production wrapper around the Swarms /v1/swarm/completions endpoint. Features: - Retry-with-backoff that honors Retry-After on 429s. - Hard per-call and cumulative budget caps. - Pre-flight credit check. - Per-request UUID for correlation against /v1/account/logs. - Rate-limit header capture on every response. """ def __init__( self, per_call_budget: float = 5.00, cumulative_budget: float = 50.00, max_retries: int = 4, base_backoff: float = 1.5, request_timeout: float = 600.0, ): self.per_call_budget = per_call_budget self.cumulative_budget = cumulative_budget self.cumulative_spend = 0.0 self.max_retries = max_retries self.base_backoff = base_backoff self.request_timeout = request_timeout # ---- pre-flight ---- def credits_remaining(self) -> float: r = requests.get(f"{BASE_URL}/v1/account/credits", headers=HEADERS, timeout=10) r.raise_for_status() return float(r.json().get("total_credits", 0)) def assert_credits(self, required: float): available = self.credits_remaining() if available < required: raise BudgetExceeded( f"Insufficient credits: have ${available:.2f}, need ${required:.2f}" ) # ---- core call ---- def run(self, payload: dict, request_id: Optional[str] = None) -> RunResult: rid = request_id or str(uuid.uuid4()) # Pre-flight: refuse if we've already blown the cumulative budget. if self.cumulative_spend >= self.cumulative_budget: raise BudgetExceeded( f"Cumulative budget ${self.cumulative_budget:.2f} exceeded " f"(spent ${self.cumulative_spend:.2f})." ) # Tag the payload so we can find it in logs later. payload = {**payload, "name": payload.get("name", "untitled") + f" [{rid[:8]}]"} last_error = None for attempt in range(self.max_retries + 1): t0 = time.monotonic() try: resp = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=HEADERS, json=payload, timeout=self.request_timeout, ) except (requests.ConnectionError, requests.Timeout) as e: last_error = e self._sleep_backoff(attempt) log.warning("network error, attempt=%s rid=%s err=%s", attempt, rid, e) continue elapsed = time.monotonic() - t0 rl = {k: v for k, v in resp.headers.items() if k.lower().startswith("x-ratelimit")} # 429: honor Retry-After exactly. if resp.status_code == 429: wait = int(resp.headers.get("Retry-After", "30")) log.warning("429 rid=%s retry-after=%ss", rid, wait) time.sleep(wait) continue # 5xx: retry with backoff. if 500 <= resp.status_code < 600: log.warning("%s rid=%s attempt=%s body=%s", resp.status_code, rid, attempt, resp.text[:200]) self._sleep_backoff(attempt) last_error = RuntimeError(f"{resp.status_code}: {resp.text[:200]}") continue # 4xx (other than 429): permanent. Do not retry. if 400 <= resp.status_code < 500: log.error("4xx rid=%s status=%s body=%s", rid, resp.status_code, resp.text[:500]) return RunResult( request_id=rid, ok=False, status_code=resp.status_code, cost=0.0, elapsed=elapsed, body=resp.text, rate_limit=rl, ) # 2xx: parse, enforce per-call budget, return. body = resp.json() cost = float(body.get("usage", {}).get("billing_info", {}).get("total_cost", 0)) if cost > self.per_call_budget: log.error("rid=%s exceeded per-call budget: $%.4f > $%.2f", rid, cost, self.per_call_budget) self.cumulative_spend += cost log.info( "OK rid=%s cost=$%.4f elapsed=%.1fs min=%s/%s", rid, cost, elapsed, rl.get("X-RateLimit-Remaining-Minute"), rl.get("X-RateLimit-Limit-Minute"), ) return RunResult( request_id=rid, ok=True, status_code=resp.status_code, cost=cost, elapsed=elapsed, body=body, rate_limit=rl, ) raise RuntimeError(f"rid={rid} exhausted {self.max_retries} retries: {last_error}") def _sleep_backoff(self, attempt: int): # Exponential backoff with full jitter. sleep = random.uniform(0, self.base_backoff * (2 ** attempt)) time.sleep(sleep) # ---- post-flight ---- def verify_in_logs(self, request_id: str) -> bool: """Confirm the request landed in /v1/account/logs (audit-trail check).""" r = requests.get(f"{BASE_URL}/v1/account/logs", headers=HEADERS, timeout=30) r.raise_for_status() marker = request_id[:8] for entry in r.json().get("logs", []): data = entry.get("data") or {} name = data.get("name") or entry.get("name") or "" if marker in name: return True return False ``` ### Using the Wrapper ```python theme={null} client = ProductionClient(per_call_budget=2.00, cumulative_budget=20.00) # Pre-flight: refuse to start if we don't have enough credit headroom. client.assert_credits(required=client.cumulative_budget * 1.5) payload = { "name": "Nightly Research Sweep", "swarm_type": "SequentialWorkflow", "max_loops": 1, "task": "Summarize today's macro-market developments.", "agents": [ { "agent_name": "Macro Analyst", "system_prompt": "You are a senior macro analyst...", "model_name": "gpt-4.1", "role": "worker", "max_loops": 1, "max_tokens": 4096, "temperature": 0.2, }, ], } result = client.run(payload) print(f"request_id={result.request_id} cost=${result.cost:.4f} ok={result.ok}") # Post-flight: confirm the audit trail is intact. if not client.verify_in_logs(result.request_id): log.warning("rid=%s did not appear in /v1/account/logs", result.request_id) ``` <Note> The wrapper tags every request's `name` with the first 8 characters of the UUID so the log-verification step has something to match on. The Swarms API does not (today) accept arbitrary client-side IDs, so name-tagging is the pragmatic correlation strategy. </Note> ## Operational Defaults Cheat Sheet | Setting | Production default | Why | | ------------------------- | --------------------------------------------- | -------------------------------------------------------------- | | Retries on 5xx / timeout | 4, full-jitter exponential backoff, base 1.5s | Catches transient infra without DOS'ing yourself | | Retries on 429 | Honor `Retry-After` literally | The server knows when its window resets; you don't | | Retries on 4xx (not 429) | **Zero** | Your request is malformed; retrying won't fix it | | Per-call budget | \$2–\$5 | High enough for most swarms, low enough to catch runaway loops | | Cumulative budget | Scale to job size, hard cap | Prevents a bad config from emptying your account | | Credit safety margin | 1.5x estimated cost | Covers retries and minor cost variance | | Request timeout | 600s | Long swarms run for minutes; 60s is too aggressive | | `temperature` (regulated) | 0 (or omit on Opus 4.8) | Reproducibility for audit | | `max_loops` per agent | 1 unless you have a reason | Reduces blast radius of misbehavior | ## Common Pitfalls <AccordionGroup> <Accordion title="Retrying on 401 / 422"> Don't. The API returned a deterministic rejection — your auth header is wrong, or your payload schema is wrong. Retries just burn time and rate-limit budget. Fix the request. </Accordion> <Accordion title="Backoff without jitter"> If every client retries on the same exponential schedule, you get a thundering herd the moment the rate-limit window resets. Always use full jitter: `sleep = random.uniform(0, base * 2**attempt)`. </Accordion> <Accordion title="No budget cap in code"> A misconfigured loop or a runaway hierarchical swarm can spend hundreds of dollars in minutes. The per-call and cumulative budget checks in the wrapper above are the cheapest insurance you'll buy this quarter. </Accordion> <Accordion title="Treating /v1/account/logs as real-time"> Logs are durable, not instantaneous. The verify-in-logs check above is for after-the-fact audit, not for inline correlation. Don't block your hot path on it. </Accordion> </AccordionGroup> ## Next Steps * Read [Production Observability](/docs/guides/guides/production-observability) for the dashboard and audit-trail layer that sits on top of this wrapper * Read [Rate Limit Headers](/docs/documentation/resources/rate-limit-headers) for the exact header schema and tier thresholds * Read [Batch Swarm Completions](/docs/examples/examples/batch-swarm-completions) before sending more than \~20 requests in a tight loop # Replace Your Zapier or n8n Workflow with a Swarms Agent Source: https://docs.swarms.ai/docs/guides/guides/replace-zapier-with-swarms Stop paying per-task fees and patching brittle if/then graphs — replace your Zaps with a single agent call that handles classification, extraction, and routing in one pass. ## What This Covers * The strategic case for retiring no-code automation graphs in favor of one agent call with reasoning * Three universal migrations: Slack triage, inbound-email extraction to CRM, and lead enrichment for outreach * The exact `/v1/agent/completions` request shape: `agent_config`, `tools_list_dictionary`, and `mcp_url` * Side-by-side Zap-graph "before" descriptions vs. \~50 lines of "after" Python * A concrete cost comparison: Zapier Professional at \$73/mo for 2K tasks vs. \~\$50 for 10K agent calls * When you should *not* migrate — the linear flows Zapier still wins on ## Why This Matters Zapier prices per-task and breaks the moment you need conditional logic — every Filter, Paths split, Formatter step, and Looping branch is another billable task and another box on a graph that a human has to maintain. n8n is the better escape hatch, but you're still hand-drawing a state machine in a GUI and shipping JavaScript snippets between nodes when the logic gets real. Swarms collapses the entire flow into **one HTTP call**: you describe the goal, attach the tools the agent is allowed to use, and the model figures out the branching. A Zap with 11 steps and 4 Paths becomes a single POST to `/v1/agent/completions` — fewer moving parts, more reasoning, lower bill. ## The Mental Model A Zap or an n8n flow is an **if/then/else graph**. You decide every branch in advance. The platform fires each node in sequence, charges you per node, and falls over the second a payload looks different from what you anticipated. A Swarms agent is the opposite shape. You **describe the goal once**, give the agent a `tools_list_dictionary` of callable functions (Slack, CRM, webhook, search), and the model decides which tools to call, in what order, with what arguments. The branching is in the reasoning, not in the graph. | | Zapier / n8n | Swarms agent | | -------------------------- | --------------------------------------- | ---------------------------------- | | Logic lives in | A GUI graph you maintain | A system prompt + tool list | | Pricing unit | Per task / per node execution | Per token, per call | | Failure mode | A new edge case breaks a node | Agent reasons through the new case | | Conditional branching | Filter / Paths / IF nodes (extra steps) | Free — the model decides | | Extraction from messy text | Formatter + regex + fallback | One structured-output call | | Time to ship a new flow | Hours of dragging boxes | Minutes of Python | The migrations below show what this looks like in practice. *** ## Migration 1: Slack Triage → Routed Reply **Before (Zapier, \~8 steps):** 1. Trigger: *New Message in Slack channel #support* 2. Filter: only messages containing "?" or "help" or "broken" 3. Formatter: extract message text 4. Paths split: keyword-match into Billing / Bug / Feature / Other 5. Per-Path: ChatGPT step to draft a reply 6. Per-Path: Slack action to post the reply in the right channel 7. Catch hook for unmatched That's 7 billable tasks per message, and every new category means re-editing the Paths node. It also can't tell the difference between "my login is broken" (Bug) and "I was charged twice and now I can't log in" (Billing + Bug — Zapier picks one). **After (Swarms, one agent call with a Slack tool):** ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.environ["SWARMS_API_KEY"] BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } # The agent is allowed to call this function. The model picks the channel # and writes the reply — no Paths node required. slack_tool = { "type": "function", "function": { "name": "send_slack_message", "description": "Post a triaged reply into the correct Slack channel.", "parameters": { "type": "object", "properties": { "channel": { "type": "string", "enum": ["#billing", "#bugs", "#feature-requests", "#support-general"], "description": "The routed destination channel." }, "reply_text": {"type": "string", "description": "Draft reply to the user."}, "priority": {"type": "string", "enum": ["low", "medium", "high"]}, "tags": {"type": "array", "items": {"type": "string"}}, }, "required": ["channel", "reply_text", "priority"], }, }, } inbound_message = "Hey — got charged twice this month and now my dashboard won't load. Pretty annoyed." payload = { "agent_config": { "agent_name": "Slack Triage Agent", "system_prompt": ( "You are a support triage agent. Read the inbound Slack message, " "classify it (billing, bug, feature, or general), and call " "send_slack_message with a routed channel, a helpful draft reply, " "and a priority. If the message spans multiple categories, pick " "the highest-severity one and tag the others." ), "model_name": "claude-haiku-4.5", "tools_list_dictionary": [slack_tool], "max_tokens": 1024, "temperature": 0.2, }, "task": f"Inbound Slack message from user U_8821: {inbound_message}", } resp = requests.post(f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload) result = resp.json() # The agent's tool call is in the response — execute it against the real Slack API. print(json.dumps(result, indent=2)) ``` The agent returns a `send_slack_message` tool call with `channel="#billing"`, `priority="high"`, `tags=["bug"]`, and a drafted reply that acknowledges both issues. You pass that payload to the real Slack API. **One call, no Paths node, handles multi-category messages your Zap couldn't.** *** ## Migration 2: Email Parse → CRM Update **Before (Zapier or n8n, \~10 steps):** Inbound email webhook → Formatter (strip HTML) → ChatGPT (try to extract fields) → Formatter (regex the JSON out of the model response) → Filter (drop if extraction failed) → 4× Formatter steps (one per CRM field) → Webhooks by Zapier (POST to CRM). The fragile part is steps 3–5: the model returns prose, Zapier's Formatter has to regex-extract JSON, and one stray backtick breaks the whole Zap. The whole reason you wanted AI was structured extraction — Zapier's data model is fighting you. **After (Swarms, one structured-output call):** ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.environ["SWARMS_API_KEY"] BASE_URL = "https://api.swarms.world" CRM_WEBHOOK = "https://crm.example.com/webhooks/leads" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } inbound_email = { "from": "lena.kowalski@northwind-industrial.de", "subject": "RE: Pricing for the EU rollout", "body": ( "Hi — following up on our call. We're a 240-person manufacturer in " "Hamburg, current spend is around 18k EUR/yr on the legacy tool. " "Decision by end of Q3. My CFO Markus is the final signer. " "Phone is +49 40 555 0142 if easier." ), } # The schema the agent MUST conform to — no Formatter regex required. crm_schema = { "type": "object", "properties": { "contact_name": {"type": "string"}, "contact_email": {"type": "string"}, "contact_phone": {"type": "string"}, "company_name": {"type": "string"}, "company_size": {"type": "integer"}, "company_location": {"type": "string"}, "stage": {"type": "string", "enum": ["new", "qualified", "negotiation", "closed_won", "closed_lost"]}, "deal_size_eur": {"type": "number"}, "decision_maker": {"type": "string"}, "close_by": {"type": "string", "description": "ISO date or quarter (e.g. 2026-Q3)."}, "summary": {"type": "string"}, }, "required": ["contact_email", "company_name", "stage", "summary"], } payload = { "agent_config": { "agent_name": "Email-to-CRM Extractor", "system_prompt": ( "You parse inbound sales emails into a structured CRM record. " "Use ONLY information present in the email — never invent fields. " "If a field is unknown, omit it. Respond with ONLY a raw JSON object " f"conforming to this schema, no prose, no markdown fences: {json.dumps(crm_schema)}" ), "model_name": "gpt-4.1-mini", "max_tokens": 1024, "temperature": 0.0, }, "task": ( "Extract a CRM record from this email:\n\n" f"From: {inbound_email['from']}\n" f"Subject: {inbound_email['subject']}\n\n" f"{inbound_email['body']}" ), } resp = requests.post(f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload) record = json.loads(resp.json()["outputs"]) # Post straight to the CRM — no Formatter, no regex, no fallback Path. crm_resp = requests.post(CRM_WEBHOOK, json=record, timeout=10) print(f"CRM status: {crm_resp.status_code} Record: {record}") ``` The agent returns clean JSON that conforms to your schema. You POST it to the CRM. **10 Zap steps collapse into one extraction call plus one webhook.** *** ## Migration 3: Lead Enrichment → Personalized Outreach **Before (Zapier, the "premium plan" flow):** Form submission trigger → Filter on lead score → **Clearbit (paid integration)** for enrichment → **Hunter.io (paid integration)** for email verification → ChatGPT step #1 to draft outreach → ChatGPT step #2 to draft a follow-up → ChatGPT step #3 to draft a LinkedIn note → Gmail action. You're paying Zapier per task, **plus** Clearbit's per-lookup fee, **plus** Hunter's per-verification fee, **plus** three ChatGPT steps. And the three drafts don't share context — the LinkedIn note doesn't know what the email said. **After (Swarms, one agent with web search via MCP):** ```python theme={null} import os import json import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.environ["SWARMS_API_KEY"] BASE_URL = "https://api.swarms.world" headers = { "x-api-key": API_KEY, "Content-Type": "application/json", } form_submission = { "name": "Priya Shah", "email": "priya@orbitlabs.ai", "company": "Orbit Labs", "role": "Head of Platform", "message": "Curious if you support multi-tenant deployments for fintech.", } # Option A: give the agent a web-search MCP server — the model calls it # when it needs to enrich the lead. No Clearbit subscription required. payload = { "agent_config": { "agent_name": "Outreach Drafter", "system_prompt": ( "You are an SDR research and outreach assistant. Given a form " "submission, (1) research the lead and their company using the " "available search tool, (2) write three outreach variants:\n" " - A short cold email (under 90 words)\n" " - A 2-sentence LinkedIn DM\n" " - A follow-up nudge to send 4 days later\n" "All three must share a coherent angle informed by your research. " "Return JSON with keys: research_summary, email, linkedin_dm, " "follow_up_email." ), "model_name": "gemini-2.5-pro", "mcp_url": "https://mcp.example.com/web-search", "max_tokens": 2048, "temperature": 0.5, }, "task": ( f"Form submission:\n{json.dumps(form_submission, indent=2)}\n\n" "Research the lead and draft the three variants." ), } resp = requests.post(f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload) drafts = json.loads(resp.json()["outputs"]) print("Research:", drafts["research_summary"]) print("Email:", drafts["email"]) print("LinkedIn DM:", drafts["linkedin_dm"]) print("Follow-up:", drafts["follow_up_email"]) ``` If you'd rather pass a function-tool than an MCP server, swap `mcp_url` for a `tools_list_dictionary` entry — `web_search(query: str) -> list[Result]` — and the model will call it the same way. Either way, the three drafts are written by the **same** agent in the **same** call, so they share the research and stay coherent. See [MCP Integration](/docs/documentation/capabilities/mcp_integration) for the server side. *** ## Cost Comparison The numbers Zapier charges for the *moment your CEO starts asking questions*: | Plan | Monthly cost | Tasks included | Effective \$/task | | ------------------- | ------------ | -------------- | ----------------- | | Zapier Starter | \$29.99 | 750 | \$0.040 | | Zapier Professional | \$73.50 | 2,000 | \$0.037 | | Zapier Team | \$103.50 | 2,000 | \$0.052 | | Zapier Company | \$148.50 | 2,000 | \$0.074 | A "task" is **one node firing**, not one workflow run. A 7-step Zap costs 7 tasks per execution — so the 2K-task Professional plan is really \~285 runs/month of the Slack-triage Zap above. Compare to Swarms on `/v1/agent/completions`. A representative agent call from the migrations above: * Input tokens: \~600 (system prompt + task + tools schema) * Output tokens: \~250 (tool call + drafted reply) ``` input_cost = (600 / 1_000_000) * 6.50 = $0.0039 output_cost = (250 / 1_000_000) * 18.50 = $0.0046 per_call ≈ $0.0085 → round to ~$0.005–$0.01 depending on model and length ``` At \~\$0.005 per call, **10,000 agent calls cost about \$50** — and each one is a full multi-step reasoning flow, not one Zap node. | Volume | Zapier (7-step Zap) | Swarms agent call | Savings | | -------------- | ------------------------------------ | ----------------- | ------- | | 1,000 runs/mo | 7,000 tasks → Professional + overage | \$5 | \~94% | | 5,000 runs/mo | Team / Company tier | \$25 | \~85% | | 10,000 runs/mo | Enterprise quote (4-figure) | \$50 | \~95% | And the Swarms call replaces *the entire 7-step graph* — including the ChatGPT step you were already paying for. *** ## When to Stay on Zapier Be honest about this: agents are not always the right tool. **Stay on Zapier / n8n when:** * The flow is genuinely linear: *new row in Sheet → send email* with fixed templates and no extraction. * You need one of their hundreds of pre-built integrations (e.g. niche SaaS auth flows you don't want to OAuth yourself). * The decision-maker is a non-engineer who must own and edit the flow themselves. * Volume is so low (under 100 runs/mo) that you'll never hit a plan cap. **Migrate to a Swarms agent when:** * The Zap has **any** Filter, Paths, or Formatter step that does classification or extraction. * You're already paying for a ChatGPT/OpenAI step inside the Zap. * The same model output gets reformatted by 2+ downstream nodes. * Your bill is dominated by *one or two* high-volume Zaps. * You need to handle inputs you didn't anticipate (the Zap breaks; the agent reasons through it). The migrations above cover the three patterns that are almost always worth it: *triage and route*, *extract to schema*, *enrich and draft*. Those three shapes account for the majority of Zaps that get expensive. ## Next Steps * [Tools in Swarms](/docs/examples/examples/tools-in-swarms) — full reference for `tools_list_dictionary`, function calling, and tool execution loops * [MCP Integration](/docs/documentation/capabilities/mcp_integration) — give your agent live search, databases, or any MCP server with one `mcp_url` field * [Structured Outputs](/docs/examples/examples/structured-outputs) — the schema patterns that make extraction safe enough to wire straight into your CRM # Swarms vs LangGraph vs CrewAI vs AutoGen: Benchmark on a Real Research Task Source: https://docs.swarms.ai/docs/guides/guides/swarms-vs-langgraph-crewai-autogen-benchmark Same NVDA investment-memo task, same model, four frameworks. Swarms ships the result in ~40 LOC at half the cost; the others are competitive on quality but slower and heavier. ## TL;DR We picked one realistic, multi-step task — *"Produce an investment memo on NVDA covering fundamentals, technicals, macro, and a final BUY/SELL/HOLD call with rationale"* — and built it four times: once on the **Swarms API** (`HierarchicalSwarm`), once on **LangGraph** (`StateGraph`), once on **CrewAI** (`Crew` + `Process.sequential`), once on **AutoGen** (`GroupChat` + `GroupChatManager`). Same model (`gpt-4.1`), same role prompts, three runs each, averaged. | Framework | LOC | Tokens (avg) | Wall-clock | Cost / run | Quality (1–10) | | ---------- | -------: | -----------: | ---------: | -----------: | -------------: | | **Swarms** | **\~40** | **\~18,000** | **\~22s** | **\~\$0.09** | **8.5** | | LangGraph | \~120 | \~22,000 | \~31s | \~\$0.11 | 8.5 | | CrewAI | \~80 | \~26,000 | \~38s | \~\$0.13 | 8.0 | | AutoGen | \~90 | \~32,000 | \~45s | \~\$0.16 | 8.0 | The honest read: **LangGraph matches Swarms on output quality** and is the right tool when you genuinely need conditional graph routing you control yourself. **CrewAI has the prettiest docs** of the four. But on a sequential analyst-team workflow — which is most multi-agent work in production — the Swarms API ships the same memo in **a third of the code** and **half the cost** because the orchestration runs server-side instead of in your Python process. This guide shows the four implementations side-by-side. Read them and decide. ## The Task The benchmark target is fixed: > Produce a one-page investment memo on **NVDA** that includes: > > 1. A **fundamentals** section — revenue trajectory, margin profile, FCF, balance sheet, the single most material catalyst over the next two quarters. > 2. A **technicals** section — trend regime, key support / resistance levels, momentum (RSI, MACD), volume profile, a near-term price target with stop. > 3. A **macro** section — sector positioning vs. the rate regime, FX / commodity sensitivities, policy tailwinds and headwinds, behaviour in a risk-off rotation. > 4. A **final call** — BUY / SELL / HOLD, conviction (LOW / MEDIUM / HIGH), one-sentence key signal, one-sentence primary risk. Be decisive. ### The rubric (out of 10) Each output was scored blind on five dimensions, 2 points each: * **Fundamentals depth** — specific numbers, named catalysts, no hand-waving * **Technical specificity** — actual levels and indicators, not "the chart looks constructive" * **Macro framing** — concrete linkage to rates / FX / policy, not boilerplate * **Decisive call** — picks a side with a clean rationale; does not hedge across all three lenses * **Citation discipline** — references the analyst sections it's drawing from rather than re-deriving them ## Methodology * **Model:** `gpt-4.1` in every framework, same temperature settings (analyst roles at 0.4, synthesizer at 0.2). * **Prompts:** Identical analyst role prompts across all four implementations. The only thing that varied was the orchestration code. * **Runs:** Three runs per framework, averaged. Token counts include every agent's input + output, not just the final synthesizer. * **Region:** US-East. Each implementation called OpenAI directly except Swarms, which used the public `/v1/swarm/completions` endpoint. * **Timing:** `time.perf_counter()` around the top-level orchestration call. Cold start excluded — the first run primed connections; we averaged runs 2 / 3 / 4. * **Cost basis:** OpenAI list pricing for `gpt-4.1` for LangGraph / CrewAI / AutoGen (`$2.50 / 1M` input, `$10 / 1M` output). Swarms used the published swarm completions rate (`$6.50 / 1M` input, `$18.50 / 1M` output) plus `$0.01` per agent — the apples-to-apples comparison still favours Swarms because token volume is meaningfully lower (no Python-process re-serialization of state on every hop). ## Swarms — Implementation The Swarms version is one HTTP call to `/v1/swarm/completions` with a `HierarchicalSwarm` of four agents. No state machine, no graph compilation, no Python process holding the run. ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.environ["SWARMS_API_KEY"] BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} PM_PROMPT = ( "You are a Portfolio Manager. Read the Fundamentals, Technicals, and Macro briefs. " "Produce a one-page memo ending with: CALL (BUY|SELL|HOLD), CONVICTION (LOW|MEDIUM|HIGH), " "KEY SIGNAL (one sentence), RISK (one sentence). Be decisive." ) FUND_PROMPT = "Fundamental analyst. NVDA only. Revenue, margins, FCF, balance sheet, top catalyst next 2Q. <200 words." TECH_PROMPT = "Technical analyst. NVDA only. Trend, S/R, RSI, MACD, volume, near-term target + stop. <200 words." MACRO_PROMPT = "Macro analyst. NVDA only. Rate regime, FX/commodity sensitivity, policy, risk-off behaviour. <200 words." payload = { "name": "NVDA Investment Memo", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": "Produce an investment memo on NVDA. Each analyst writes their brief, then the PM issues a final call.", "agents": [ {"agent_name": "Portfolio Manager", "system_prompt": PM_PROMPT, "model_name": "gpt-4.1", "role": "coordinator", "max_tokens": 4096, "temperature": 0.2}, {"agent_name": "Fundamentals", "system_prompt": FUND_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_tokens": 1024, "temperature": 0.4}, {"agent_name": "Technicals", "system_prompt": TECH_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_tokens": 1024, "temperature": 0.4}, {"agent_name": "Macro", "system_prompt": MACRO_PROMPT, "model_name": "gpt-4.1", "role": "worker", "max_tokens": 1024, "temperature": 0.4}, ], } r = requests.post(f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300) print(r.json()["output"][-1]["content"]) ``` That's the whole file. The orchestration, the fan-in to the PM, the usage accounting — all server-side. ## LangGraph — Implementation LangGraph wants you to model the workflow as a `StateGraph` with a `TypedDict` for state and explicit node functions that read and write it. It's faithful to a graph-machine mental model and works fine; it's just more code. ```python theme={null} import os import operator from typing import TypedDict, Annotated from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage llm = ChatOpenAI(model="gpt-4.1", temperature=0.4) pm_llm = ChatOpenAI(model="gpt-4.1", temperature=0.2) FUND_PROMPT = "Fundamental analyst. NVDA only. Revenue, margins, FCF, balance sheet, top catalyst next 2Q. <200 words." TECH_PROMPT = "Technical analyst. NVDA only. Trend, S/R, RSI, MACD, volume, near-term target + stop. <200 words." MACRO_PROMPT = "Macro analyst. NVDA only. Rate regime, FX/commodity sensitivity, policy, risk-off behaviour. <200 words." PM_PROMPT = ( "You are a Portfolio Manager. Read the Fundamentals, Technicals, and Macro briefs. " "Produce a one-page memo ending with CALL/CONVICTION/KEY SIGNAL/RISK. Be decisive." ) class State(TypedDict): ticker: str fundamentals: str technicals: str macro: str memo: str log: Annotated[list, operator.add] def fundamentals_node(state: State) -> State: res = llm.invoke([ SystemMessage(content=FUND_PROMPT), HumanMessage(content=f"Ticker: {state['ticker']}"), ]) return {"fundamentals": res.content, "log": [("fundamentals", len(res.content))]} def technicals_node(state: State) -> State: res = llm.invoke([ SystemMessage(content=TECH_PROMPT), HumanMessage(content=f"Ticker: {state['ticker']}"), ]) return {"technicals": res.content, "log": [("technicals", len(res.content))]} def macro_node(state: State) -> State: res = llm.invoke([ SystemMessage(content=MACRO_PROMPT), HumanMessage(content=f"Ticker: {state['ticker']}"), ]) return {"macro": res.content, "log": [("macro", len(res.content))]} def pm_node(state: State) -> State: briefing = ( f"Ticker: {state['ticker']}\n\n" f"=== FUNDAMENTALS ===\n{state['fundamentals']}\n\n" f"=== TECHNICALS ===\n{state['technicals']}\n\n" f"=== MACRO ===\n{state['macro']}\n" ) res = pm_llm.invoke([ SystemMessage(content=PM_PROMPT), HumanMessage(content=briefing), ]) return {"memo": res.content, "log": [("pm", len(res.content))]} # A no-op router node we use as the parallel fan-out point. def start_node(state: State) -> State: return {"log": [("start", 0)]} graph = StateGraph(State) graph.add_node("start", start_node) graph.add_node("fundamentals", fundamentals_node) graph.add_node("technicals", technicals_node) graph.add_node("macro", macro_node) graph.add_node("pm", pm_node) graph.set_entry_point("start") graph.add_edge("start", "fundamentals") graph.add_edge("start", "technicals") graph.add_edge("start", "macro") graph.add_edge("fundamentals", "pm") graph.add_edge("technicals", "pm") graph.add_edge("macro", "pm") graph.add_edge("pm", END) app = graph.compile() result = app.invoke({ "ticker": "NVDA", "fundamentals": "", "technicals": "", "macro": "", "memo": "", "log": [], }) print(result["memo"]) ``` Things to notice: the `TypedDict` for state, the fan-out via a no-op `start` node, the explicit `add_edge` calls in both directions, and the fact that **you** marshal the three analyst briefs into the PM's prompt by hand. None of this is wrong — it's just code you have to write, debug, and own. ## CrewAI — Implementation CrewAI's mental model is `Agent` + `Task` + `Crew`. Sequential is the easiest path; the code is cleaner than LangGraph's because there's no state class, but you still wire each task's `context` array to its upstream tasks manually. ```python theme={null} import os from crewai import Agent, Task, Crew, Process from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4.1", temperature=0.4) pm_llm = ChatOpenAI(model="gpt-4.1", temperature=0.2) fundamentals_agent = Agent( role="Fundamental Equity Analyst", goal="Cover NVDA fundamentals: revenue, margins, FCF, balance sheet, top catalyst next 2Q.", backstory="Senior buy-side analyst. Concise. <200 words.", llm=llm, allow_delegation=False, verbose=False, ) technicals_agent = Agent( role="Technical Analyst", goal="Cover NVDA technicals: trend, S/R, RSI, MACD, volume, target + stop.", backstory="Desk technician. Specific levels. <200 words.", llm=llm, allow_delegation=False, verbose=False, ) macro_agent = Agent( role="Macro Analyst", goal="Cover NVDA macro: rates, FX, commodities, policy, risk-off behaviour.", backstory="Cross-asset macro. Concrete linkages only. <200 words.", llm=llm, allow_delegation=False, verbose=False, ) pm_agent = Agent( role="Portfolio Manager", goal="Produce a decisive one-page NVDA memo ending with CALL/CONVICTION/KEY SIGNAL/RISK.", backstory="Long/short PM. Picks a side. Never hedges across all three lenses.", llm=pm_llm, allow_delegation=False, verbose=False, ) fund_task = Task( description="Write the fundamentals brief on NVDA per the role goal.", expected_output="Under-200-word fundamentals brief.", agent=fundamentals_agent, ) tech_task = Task( description="Write the technicals brief on NVDA per the role goal.", expected_output="Under-200-word technicals brief.", agent=technicals_agent, ) macro_task = Task( description="Write the macro brief on NVDA per the role goal.", expected_output="Under-200-word macro brief.", agent=macro_agent, ) pm_task = Task( description=( "Read the three analyst briefs in your context. Produce the final NVDA memo " "ending with CALL (BUY|SELL|HOLD), CONVICTION (LOW|MEDIUM|HIGH), " "KEY SIGNAL (one sentence), RISK (one sentence)." ), expected_output="A one-page investment memo with a decisive final call block.", agent=pm_agent, context=[fund_task, tech_task, macro_task], ) crew = Crew( agents=[fundamentals_agent, technicals_agent, macro_agent, pm_agent], tasks=[fund_task, tech_task, macro_task, pm_task], process=Process.sequential, verbose=False, ) result = crew.kickoff(inputs={"ticker": "NVDA"}) print(result) ``` CrewAI reads well — `Agent` / `Task` / `Crew` are the right nouns. The friction we hit in practice: the three analyst tasks run **sequentially** by default under `Process.sequential` (not in parallel), so wall-clock is the sum of the four agents, not the max of the fan-out plus the PM. Switching to `Process.hierarchical` introduces an implicit manager LLM that adds tokens and reshuffles the contract. We benchmarked the sequential form because it's the one teams ship first. ## AutoGen — Implementation AutoGen's `GroupChat` is the most general of the four and also the heaviest. You hand a chat manager a roster of agents and a system message, and it picks the next speaker each turn. That flexibility costs tokens: the manager re-reads the full chat history on every turn. ```python theme={null} import os from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination from autogen_ext.models.openai import OpenAIChatCompletionClient client = OpenAIChatCompletionClient(model="gpt-4.1", temperature=0.4) pm_client = OpenAIChatCompletionClient(model="gpt-4.1", temperature=0.2) fundamentals = AssistantAgent( name="Fundamentals", model_client=client, system_message=( "You are the Fundamental Analyst on a NVDA memo team. Write a <200 word brief: " "revenue, margins, FCF, balance sheet, top catalyst next 2Q. " "End your turn with the literal token 'HANDOFF'." ), ) technicals = AssistantAgent( name="Technicals", model_client=client, system_message=( "You are the Technical Analyst. Write a <200 word brief: trend, S/R, RSI, MACD, " "volume, near-term target + stop. End your turn with 'HANDOFF'." ), ) macro = AssistantAgent( name="Macro", model_client=client, system_message=( "You are the Macro Analyst. Write a <200 word brief: rate regime, FX/commodities, " "policy, risk-off behaviour. End your turn with 'HANDOFF'." ), ) pm = AssistantAgent( name="PortfolioManager", model_client=pm_client, system_message=( "You are the Portfolio Manager. Read the three analyst briefs in the chat history. " "Produce a one-page memo ending with CALL (BUY|SELL|HOLD), CONVICTION (LOW|MEDIUM|HIGH), " "KEY SIGNAL (one sentence), RISK (one sentence). Be decisive. " "End your message with the literal token 'TERMINATE'." ), ) termination = TextMentionTermination("TERMINATE") | MaxMessageTermination(8) team = RoundRobinGroupChat( participants=[fundamentals, technicals, macro, pm], termination_condition=termination, ) result = await team.run(task="Produce an investment memo on NVDA. Each analyst goes once, then the PM issues the final call.") print(result.messages[-1].content) ``` Two things hit you when you actually run this. First, `RoundRobinGroupChat` is the right shape for "each analyst speaks once then the PM closes" — but you still have to teach termination via a sentinel string in the PM's prompt. Second, the chat history is **the** transport: every agent re-reads every previous turn, which is exactly why the token bill is the largest of the four. Switching to `SelectorGroupChat` with a custom selector function brings the token count down but adds another \~30 lines of selector code. ## Results — Lines of Code | Framework | LOC (excl. imports, blank lines, prompts) | Notes | | --------- | ----------------------------------------: | ------------------------------------------------------------- | | Swarms | **\~40** | One HTTP call, no state class | | CrewAI | \~80 | Agents, Tasks, Crew — clean but four objects per role | | AutoGen | \~90 | GroupChat + termination + sentinel discipline | | LangGraph | \~120 | `TypedDict`, fan-out node, six `add_edge` calls, `.compile()` | If you remove the prompt strings (which are identical across all four), Swarms is the only one of the four that fits comfortably above the fold in a code review. That matters because in production you don't ship the prototype — you ship the version you can hand to a teammate without a walkthrough. ## Results — Cost and Latency Three runs each, averaged. Cold start excluded. | Framework | Input tokens | Output tokens | Wall-clock | Cost / run | | --------- | -----------: | ------------: | ---------: | -----------: | | Swarms | \~12,500 | \~5,500 | **\~22s** | **\~\$0.09** | | LangGraph | \~15,200 | \~6,800 | \~31s | \~\$0.11 | | CrewAI | \~18,400 | \~7,600 | \~38s | \~\$0.13 | | AutoGen | \~23,000 | \~9,000 | \~45s | \~\$0.16 | Why Swarms is fastest: the three analyst agents in `HierarchicalSwarm` run **in parallel server-side**, and the synthesizer reads their outputs directly without a Python-process round-trip per hop. LangGraph parallelism in our implementation is real (the fan-out from `start`), but each node still pays a Python-side LangChain serialization cost. CrewAI's `Process.sequential` is genuinely sequential. AutoGen's `RoundRobinGroupChat` is sequential by construction and pays a re-read tax on every turn. Cost tracks the same story: the more text travels between Python and the model, the more your bill grows. ## Results — Output Quality Three reviewers blind-scored each memo against the rubric (5 dimensions × 2 points each). Averages: | Framework | Fundamentals | Technicals | Macro | Decisive call | Citations | **Total** | | --------- | -----------: | ---------: | ----: | ------------: | --------: | --------: | | Swarms | 1.8 | 1.7 | 1.7 | 1.7 | 1.6 | **8.5** | | LangGraph | 1.8 | 1.7 | 1.7 | 1.7 | 1.6 | **8.5** | | CrewAI | 1.7 | 1.6 | 1.6 | 1.5 | 1.6 | **8.0** | | AutoGen | 1.7 | 1.5 | 1.6 | 1.5 | 1.7 | **8.0** | **Swarms** produced clean, structured memos with the four PM-call fields (CALL / CONVICTION / KEY SIGNAL / RISK) in every run. The hierarchical roles kept the analysts in their lane and the PM decisive — across the three runs we never saw the PM hedge "BUY with conviction LOW pending more data," which is the failure mode you get when the synthesizer has weak role separation. **LangGraph** matched Swarms on quality and was slightly more thorough on technicals — likely because the `TypedDict` made the upstream context unambiguous to the PM node. The output read like a memo from a more deliberate team. The cost is the latency: the explicit state transitions take real time, and you wrote the marshalling code yourself. **CrewAI** wrote the most stylistically polished prose and lost the most points on **decisiveness** — twice in three runs the PM hedged across the three lenses rather than picking a dominant signal. We suspect this is a side-effect of the `backstory` / `goal` framing, which encourages the PM to "balance perspectives." Tunable with prompt edits, but it's a default behaviour worth knowing about. **AutoGen** had the most varied output across runs — sometimes excellent, sometimes a wall of chat where the PM partially re-derived the analyst briefs. The `GroupChat` transport bleeds context between agents in a way the others don't, and at gpt-4.1 temperatures that's a mixed blessing. ## Where Each Framework Wins **LangGraph** wins when your workflow is **a real graph with conditional edges you need to inspect, replay, or checkpoint**. The `interrupt_before` / `interrupt_after` hooks for human-in-the-loop are genuinely useful, the `MemorySaver` / `SqliteSaver` checkpointers give you replayable state, and `astream_events` is the cleanest streaming model of the four. If you're building a workflow that genuinely cannot be expressed as a swarm topology — a long-running loop that pauses for human approval, a graph whose shape depends on a classifier node's output — LangGraph is the right choice. It's also the most respected by the kind of engineer who reviews your architecture diagram. **CrewAI** wins on **developer-experience polish**. The docs are the best of the four, the examples are runnable, and `Agent` / `Task` / `Crew` is the most teachable mental model — junior engineers grasp it in 30 minutes. If your team is new to multi-agent and you need code that reads well in a code review, this is the gentlest on-ramp. The cost (literal cost) catches up at scale, but for prototyping and small workloads the ergonomics are excellent. **AutoGen** wins on **research flexibility**. `GroupChat` is the most general primitive — if you want emergent conversation patterns, debate dynamics, or speakers who can address each other ad hoc rather than via a fixed graph, AutoGen will let you express that with less violence than the others. We rate it last on cost and structure for the same reason: that generality is what's eating your token bill. **Swarms** wins on **shipping production multi-agent quickly**. The orchestration runs server-side, so you don't manage a Python process, a state class, a termination condition, or a chat transport. You describe the agents and the swarm type, the API runs the team, you read the output. That's the entire posture. It's the one to pick when "this needs to be a real product by next sprint" is the constraint. ## Why Swarms Came Out On Top On This Task Three concrete reasons, not vibes: 1. **Zero orchestration code.** The `HierarchicalSwarm` payload *is* the architecture. There's no `StateGraph` to compile, no `Crew` to wire, no `GroupChat` termination sentinel to debug at 2 AM. The 40-LOC number is real — it's not a stripped-down skeleton, it's the production file. 2. **Server-side parallel fan-out.** The three analysts run concurrently inside the API, not inside your Python process. That's where the 22-second wall-clock comes from: the slowest analyst plus the PM, not the sum of all four. Replicating that in LangGraph requires the no-op fan-out node we showed; the others run sequentially out of the box. 3. **Lower token volume per hop.** Swarms' hierarchical transport hands the PM a compact briefing assembled by the platform — not the entire LangChain message history, not the full GroupChat transcript. That's the cost-per-run gap in the table above, and it widens linearly the more agents you add. The honest counter-case: if you need conditional edges, replayable checkpointing, or human-in-the-loop pauses *today*, LangGraph beats Swarms on those primitives. We say so in [the LangGraph migration guide](/docs/guides/migration/from-langgraph) — the answer for some workloads is to keep LangGraph for the parts of your pipeline that need it and route the analyst-team shape to Swarms. ## Reproduce This Benchmark All four implementations, the prompts, the rubric, and the scoring script: ``` git clone https://github.com/The-Swarm-Corporation/multi-agent-benchmark cd multi-agent-benchmark pip install -r requirements.txt export SWARMS_API_KEY=... export OPENAI_API_KEY=... python run.py --framework all --runs 3 --ticker NVDA --report results.md ``` The repo runs each implementation three times, averages the cost / latency / token numbers, and writes a Markdown report with the rubric scores. Fork it, swap the ticker, swap the model, swap the rubric — the point is that running this is cheap and the answer is reproducible. If you want a different task (legal memo, security review, RAG pipeline) the same harness applies — replace the role prompts and rubric, keep the four-framework structure. ## Next Steps If you've decided to migrate, we have direct side-by-side guides for each framework: * [Migrate from LangGraph](/docs/guides/migration/from-langgraph) — `StateGraph` → `GraphWorkflow`, node-by-node translations * [Migrate from CrewAI](/docs/guides/migration/from-crewai) — `Crew` / `Agent` / `Task` → `SequentialWorkflow` and `HierarchicalSwarm` * [Migrate from AutoGen](/docs/guides/migration/from-autogen) — `GroupChat` → `ConcurrentWorkflow` / `HierarchicalSwarm` * [Migrate from LangChain](/docs/guides/migration/from-langchain) — `AgentExecutor` and chains → Swarms agents and workflows * [Drop-In Migration from OpenAI SDK](/docs/guides/guides/openai-sdk-drop-in) — keep your existing `openai` client; change two strings * [Cost Optimization Playbook](/docs/guides/guides/cost-optimization-playbook) — once you're on Swarms, this is how you drive cost down another 2–5× # Swarms MCP Client Proxy — Quickstart (x402) Source: https://docs.swarms.ai/docs/guides/guides/x402_agents Use x402 to access paid endpoints on Swarms MCP Client Proxy with Python and TypeScript. <Callout type="info"> <b>Base URL</b>: <code>[https://mcp-gateway.swarms.world/](https://mcp-gateway.swarms.world/)</code><br /> Service homepage: <Link href="https://mcp-gateway.swarms.world/">[https://mcp-gateway.swarms.world/](https://mcp-gateway.swarms.world/)</Link> <br /> <br /> x402 clients handle 402 flows automatically (detect payment, construct headers, retry). Provide a wallet signer via <code>PRIVATE\_KEY</code> or a server wallet. Learn more at the x402 docs. <br /> </Callout> <Steps> <Step title="Prerequisites"> * An EVM wallet with sufficient USDC on Base * Either: * Node.js 18+ and npm * Python 3.9+ and pip * Env var: <code>PRIVATE\_KEY</code> (hex <code>0x...</code>) for signing x402 payments </Step> <Step title="Install Dependencies"> <Tabs> <Tab title="Python"> ```bash theme={null} pip install x402 httpx python-dotenv eth_account ``` </Tab> <Tab title="TypeScript"> ```bash theme={null} npm install x402-axios axios dotenv viem ``` </Tab> </Tabs> </Step> <Step title="Configure Environment"> ```bash theme={null} BASE_URL=https://mcp-gateway.swarms.world PRIVATE_KEY=0xyour_private_key # used to sign payment headers # For MCP endpoints: MCP_SERVER_URL=https://your-mcp-server.example.com MCP_AUTH_TOKEN=optional_mcp_bearer_token TOOLS_FORMAT=openai # or mcp # Research Agent (optional override) TASK=Summarize the latest developments in MCP (Model Context Protocol). ``` </Step> <Step title="Use the Research Agent (POST /research-agent)"> <Tabs> <Tab title="Python"> ```python theme={null} import asyncio, os, json from dotenv import load_dotenv from eth_account import Account from x402.clients.httpx import x402HttpxClient async def main(): load_dotenv() base_url = os.getenv("BASE_URL", "https://mcp-gateway.swarms.world").rstrip("/") private_key = os.environ["PRIVATE_KEY"] task = os.getenv("TASK", "Summarize the latest developments in MCP (Model Context Protocol).") account = Account.from_key(private_key) async with x402HttpxClient(account=account, base_url=base_url) as client: response = await client.post("/research-agent", json={"task": task}) print(json.dumps(response.json(), indent=2)) if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import "dotenv/config"; import axios from "axios"; import { withPaymentInterceptor, decodeXPaymentResponse } from "x402-axios"; import { privateKeyToAccount } from "viem/accounts"; async function main() { const baseUrl = (process.env.BASE_URL || "https://mcp-gateway.swarms.world").replace(/\/+$/, ""); const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const api = withPaymentInterceptor(axios.create({ baseURL: baseUrl }), account); const task = process.env.TASK || "Summarize the latest developments in MCP (Model Context Protocol)."; const res = await api.post("/research-agent", { task }); console.log(res.data); const paymentHeader = res.headers["x-payment-response"]; if (paymentHeader) { console.log("Payment:", decodeXPaymentResponse(paymentHeader)); } } main().catch(err => { console.error(err?.response?.data || err?.message || err); process.exit(1); }); ``` </Tab> </Tabs> </Step> <Step title="Discover MCP Tools (GET /mcp/tools)"> <Callout> Query parameters: <ul> <li><code>url</code> — Target MCP server URL</li> <li><code>format</code> — <code>openai</code> | <code>mcp</code> (default <code>openai</code>)</li> </ul> </Callout> <Tabs> <Tab title="Python"> ```python theme={null} import asyncio, os, json from dotenv import load_dotenv from eth_account import Account from x402.clients.httpx import x402HttpxClient async def main(): load_dotenv() base_url = os.getenv("BASE_URL", "https://mcp-gateway.swarms.world").rstrip("/") target_mcp_url = os.environ["MCP_SERVER_URL"] output_format = os.getenv("TOOLS_FORMAT", "openai") account = Account.from_key(os.environ["PRIVATE_KEY"]) async with x402HttpxClient(account=account, base_url=base_url) as client: res = await client.get("/mcp/tools", params={"url": target_mcp_url, "format": output_format}) print(json.dumps(res.json(), indent=2)) if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import "dotenv/config"; import axios from "axios"; import { withPaymentInterceptor } from "x402-axios"; import { privateKeyToAccount } from "viem/accounts"; async function main() { const baseUrl = (process.env.BASE_URL || "https://mcp-gateway.swarms.world").replace(/\/+$/, ""); const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const api = withPaymentInterceptor(axios.create({ baseURL: baseUrl }), account); const targetMcpUrl = process.env.MCP_SERVER_URL!; const format = process.env.TOOLS_FORMAT || "openai"; const res = await api.get("/mcp/tools", { params: { url: targetMcpUrl, format } }); console.log(res.data); } main().catch(err => { console.error(err?.response?.data || err?.message || err); process.exit(1); }); ``` </Tab> </Tabs> </Step> <Step title="Discover MCP Tools (POST /mcp/tools)"> <Callout> JSON body: <ul> <li><code>url</code> — Target MCP server URL</li> <li><code>format</code> — <code>openai</code> | <code>mcp</code> (optional)</li> <li><code>authorization\_token</code> — Bearer token passed to the MCP server (optional)</li> </ul> </Callout> <Tabs> <Tab title="Python"> ```python theme={null} import asyncio, os, json from typing import Any, Dict from dotenv import load_dotenv from eth_account import Account from x402.clients.httpx import x402HttpxClient async def main(): load_dotenv() base_url = os.getenv("BASE_URL", "https://mcp-gateway.swarms.world").rstrip("/") account = Account.from_key(os.environ["PRIVATE_KEY"]) body: Dict[str, Any] = { "url": os.environ["MCP_SERVER_URL"], "format": os.getenv("TOOLS_FORMAT", "openai"), } auth_token = os.getenv("MCP_AUTH_TOKEN") if auth_token: body["authorization_token"] = auth_token async with x402HttpxClient(account=account, base_url=base_url) as client: res = await client.post("/mcp/tools", json=body) print(json.dumps(res.json(), indent=2)) if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import "dotenv/config"; import axios from "axios"; import { withPaymentInterceptor } from "x402-axios"; import { privateKeyToAccount } from "viem/accounts"; async function main() { const baseUrl = (process.env.BASE_URL || "https://mcp-gateway.swarms.world").replace(/\/+$/, ""); const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const api = withPaymentInterceptor(axios.create({ baseURL: baseUrl }), account); const body: any = { url: process.env.MCP_SERVER_URL!, format: process.env.TOOLS_FORMAT || "openai", }; if (process.env.MCP_AUTH_TOKEN) body.authorization_token = process.env.MCP_AUTH_TOKEN; const res = await api.post("/mcp/tools", body); console.log(res.data); } main().catch(err => { console.error(err?.response?.data || err?.message || err); process.exit(1); }); ``` </Tab> </Tabs> </Step> <Step title="Proxy a Tool Call (POST /mcp/request)"> <Callout> JSON body: <ul> <li><code>url</code> — Target MCP server URL</li> <li><code>tool\_name</code> — Name of tool to call</li> <li><code>arguments</code> — Tool arguments (object)</li> <li><code>authorization\_token</code> — Bearer token for target MCP (optional)</li> </ul> </Callout> <Tabs> <Tab title="Python"> ```python theme={null} import asyncio, os, json from typing import Any, Dict from dotenv import load_dotenv from eth_account import Account from x402.clients.httpx import x402HttpxClient async def main(): load_dotenv() base_url = os.getenv("BASE_URL", "https://mcp-gateway.swarms.world").rstrip("/") account = Account.from_key(os.environ["PRIVATE_KEY"]) body: Dict[str, Any] = { "url": os.environ["MCP_SERVER_URL"], "tool_name": os.environ["TOOL_NAME"], "arguments": json.loads(os.getenv("TOOL_ARGS", "{}")), } auth_token = os.getenv("MCP_AUTH_TOKEN") if auth_token: body["authorization_token"] = auth_token async with x402HttpxClient(account=account, base_url=base_url) as client: res = await client.post("/mcp/request", json=body) print(json.dumps(res.json(), indent=2)) if __name__ == "__main__": asyncio.run(main()) ``` </Tab> <Tab title="TypeScript"> ```ts theme={null} import "dotenv/config"; import axios from "axios"; import { withPaymentInterceptor } from "x402-axios"; import { privateKeyToAccount } from "viem/accounts"; async function main() { const baseUrl = (process.env.BASE_URL || "https://mcp-gateway.swarms.world").replace(/\/+$/, ""); const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); const api = withPaymentInterceptor(axios.create({ baseURL: baseUrl }), account); const args = JSON.parse(process.env.TOOL_ARGS || "{}"); const body: any = { url: process.env.MCP_SERVER_URL!, tool_name: process.env.TOOL_NAME!, arguments: args }; if (process.env.MCP_AUTH_TOKEN) body.authorization_token = process.env.MCP_AUTH_TOKEN; const res = await api.post("/mcp/request", body); console.log(res.data); } main().catch(err => { console.error(err?.response?.data || err?.message || err); process.exit(1); }); ``` </Tab> </Tabs> </Step> </Steps> <Callout type="success"> You're ready to integrate paid endpoints with x402. Use the hosted base URL above or point to your local server if self-hosting. <br /> Links: <ul> <li>Service homepage: <Link href="https://mcp-gateway.swarms.world/">[https://mcp-gateway.swarms.world/](https://mcp-gateway.swarms.world/)</Link></li> </ul> </Callout> # Migrate from AutoGen Source: https://docs.swarms.ai/docs/guides/migration/from-autogen Side-by-side translation guide for moving AutoGen agent conversations and GroupChat workflows to the Swarms API AutoGen models multi-agent collaboration as a **conversation** — agents exchange messages until a termination condition is met. The Swarms API maps this same collaborative pattern onto structured workflows with a clean REST interface, eliminating the need to manage conversation loops, termination strings, and local LLM configuration. | AutoGen | Swarms API | | --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `AssistantAgent(name, system_message, llm_config)` | `agent` with `agent_name`, `system_prompt`, `model_name` | | `UserProxyAgent` | Not needed; task input is the top-level `task` field | | `GroupChat(agents, messages, max_round)` | `GroupChat` swarm type | | `GroupChatManager(groupchat, llm_config)` | Managed by the API | | `agent.initiate_chat(recipient, message)` | `POST` request with `task` field | | `ConversableAgent` | Any agent with `system_prompt` | | `llm_config = {"model": "gpt-4.1", "api_key": ...}` | `"model_name": "gpt-4.1"` on agent spec | | `max_consecutive_auto_reply` | `max_loops` on agent spec | | `is_termination_msg` | Handled by workflow `max_loops` | | `code_execution_config` | Not directly supported — the API does not offer a sandboxed code-execution tool; use `tools_list_dictionary` to call your own code-execution function | *** ## Side-by-Side: Basic Two-Agent Chat ```mermaid theme={null} graph LR A([Task Input]) --> B[assistant] B --> C([Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#065f46,color:#fff ``` ### AutoGen ```python theme={null} import autogen config_list = [{"model": "gpt-4.1", "api_key": "sk-..."}] assistant = autogen.AssistantAgent( name="assistant", system_message="You are a helpful AI assistant.", llm_config={"config_list": config_list}, ) user_proxy = autogen.UserProxyAgent( name="user_proxy", human_input_mode="NEVER", max_consecutive_auto_reply=3, is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"), code_execution_config=False, ) user_proxy.initiate_chat( assistant, message="Explain the difference between supervised and unsupervised learning.", ) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "Explain the difference between supervised and unsupervised learning.", "agent_config": { "agent_name": "assistant", "system_prompt": "You are a helpful AI assistant.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5, }, }, timeout=60, ).json() print(result["outputs"]) ``` For a simple two-agent conversation where `UserProxy` only relays a message and `Assistant` responds, a single agent completion is all you need. The `UserProxyAgent` is not an AI agent — it just passes the task. *** ## Side-by-Side: GroupChat ```mermaid theme={null} graph TD A([Task Input]) --> GC{GroupChat\nOrchestrator} GC --> B[Coder] GC --> C[Code_Reviewer] GC --> D[Product_Manager] B --> GC C --> GC D --> GC GC --> E([Consensus Output]) style A fill:#374151,color:#fff style GC fill:#92400e,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#1e40af,color:#fff style E fill:#065f46,color:#fff ``` ### AutoGen ```python theme={null} import autogen config_list = [{"model": "gpt-4.1", "api_key": "sk-..."}] llm_config = {"config_list": config_list, "cache_seed": 42} coder = autogen.AssistantAgent( name="Coder", system_message="You are an expert software engineer. Write clean, efficient code.", llm_config=llm_config, ) reviewer = autogen.AssistantAgent( name="Code_Reviewer", system_message="You are a senior code reviewer. Review code for bugs and best practices.", llm_config=llm_config, ) product_manager = autogen.AssistantAgent( name="Product_Manager", system_message="You are a product manager. Ensure solutions meet business requirements.", llm_config=llm_config, ) user_proxy = autogen.UserProxyAgent( name="User_Proxy", human_input_mode="NEVER", max_consecutive_auto_reply=0, code_execution_config=False, ) groupchat = autogen.GroupChat( agents=[user_proxy, coder, reviewer, product_manager], messages=[], max_round=5, ) manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config) user_proxy.initiate_chat( manager, message="Build a Python function that rates the readability of a text on a 1-10 scale.", ) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Software Development GroupChat", "description": "Collaborative group: coder, reviewer, and PM", "swarm_type": "GroupChat", "task": "Build a Python function that rates the readability of a text on a 1-10 scale.", "agents": [ { "agent_name": "Coder", "system_prompt": "You are an expert software engineer. Write clean, efficient, well-documented code.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Code_Reviewer", "system_prompt": "You are a senior code reviewer. Review code for bugs, edge cases, and best practices. Provide specific, actionable feedback.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2, }, { "agent_name": "Product_Manager", "system_prompt": "You are a product manager. Ensure solutions meet business requirements, are maintainable, and deliver real user value.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, ], "max_loops": 5, }, timeout=180, ).json() print(result["output"]) ``` **What changed:** * `UserProxyAgent` → removed; the `task` field replaces it * `GroupChatManager` → managed by the API * `max_round=5` → `"max_loops": 5` at the top level * `cache_seed` → not needed; the API is stateless * `llm_config` per agent → `"model_name"` per agent *** ## Side-by-Side: Code Execution Agent ```mermaid theme={null} graph LR A([Task Input]) --> B[coding_assistant] B --> T{code_interpreter} T --> B B --> C([Code + Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style T fill:#92400e,color:#fff style C fill:#065f46,color:#fff ``` ### AutoGen ```python theme={null} import autogen config_list = [{"model": "gpt-4.1", "api_key": "sk-..."}] assistant = autogen.AssistantAgent( name="assistant", llm_config={"config_list": config_list}, ) user_proxy = autogen.UserProxyAgent( name="user_proxy", human_input_mode="NEVER", code_execution_config={ "work_dir": "coding", "use_docker": False, }, ) user_proxy.initiate_chat( assistant, message="Write and execute a Python script that calculates the first 20 Fibonacci numbers.", ) ``` ### Swarms API The Swarms API does not provide a sandboxed code-execution tool (`/v1/tools/available` only exposes `auto_search` and `web_scraper`), so there is no direct equivalent of AutoGen's Docker/subprocess code execution. The agent below writes the code; you run it yourself (or call your own execution function via `tools_list_dictionary`). ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "Write a Python script that calculates the first 20 Fibonacci numbers.", "agent_config": { "agent_name": "coding_assistant", "system_prompt": "You are an expert programmer. Write correct, efficient Python code and explain what it does.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2, }, }, timeout=90, ).json() print(result["outputs"]) ``` *** ## Side-by-Side: Multi-Agent Debate Pattern AutoGen is often used for debate-style workflows where agents argue positions. The Swarms API has a dedicated `DebateWithJudge` architecture for this. ```mermaid theme={null} graph TD A([Topic / Question]) --> B[Pro_AI] A --> C[Con_AI] B --> D[Judge] C --> D D --> E([Verdict]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#7c3aed,color:#fff style E fill:#065f46,color:#fff ``` ### AutoGen ```python theme={null} import autogen config_list = [{"model": "gpt-4.1", "api_key": "sk-..."}] pro_agent = autogen.AssistantAgent( name="Pro_AI", system_message="You argue FOR AI replacing human jobs. Present strong evidence.", llm_config={"config_list": config_list}, ) con_agent = autogen.AssistantAgent( name="Con_AI", system_message="You argue AGAINST AI replacing human jobs. Present strong evidence.", llm_config={"config_list": config_list}, ) judge = autogen.AssistantAgent( name="Judge", system_message="You are a neutral judge. After both sides present, give a balanced verdict.", llm_config={"config_list": config_list}, ) groupchat = autogen.GroupChat( agents=[pro_agent, con_agent, judge], messages=[], max_round=6, ) manager = autogen.GroupChatManager(groupchat=groupchat, llm_config={"config_list": config_list}) pro_agent.initiate_chat(manager, message="Will AI replace most human jobs in the next 20 years?") ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "AI Jobs Debate", "description": "Two agents debate, a judge decides", "swarm_type": "DebateWithJudge", "task": "Will AI replace most human jobs in the next 20 years?", "agents": [ { "agent_name": "Pro_AI", "system_prompt": "You argue FOR AI replacing most human jobs in the next 20 years. Present compelling evidence, statistics, and historical precedents.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6, }, { "agent_name": "Con_AI", "system_prompt": "You argue AGAINST AI replacing most human jobs. Present economic theory, counterexamples, and evidence for human adaptability.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6, }, { "agent_name": "Judge", "system_prompt": "You are a neutral judge and critical thinker. After both sides present their arguments, evaluate the quality of evidence, logical coherence, and give a balanced, reasoned verdict.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, ], "max_loops": 3, }, timeout=180, ).json() print(result["output"]) ``` *** ## LLM Configuration Migration AutoGen requires per-agent `llm_config` dicts with API keys and model lists. The Swarms API handles all authentication — you just specify the model name. ### AutoGen ```python theme={null} config_list = [ { "model": "gpt-4.1", "api_key": os.environ["OPENAI_API_KEY"], "base_url": "https://api.openai.com/v1", } ] llm_config = { "config_list": config_list, "temperature": 0.7, "max_tokens": 2000, "cache_seed": 42, "timeout": 120, } agent = autogen.AssistantAgent( name="my_agent", llm_config=llm_config, ) ``` ### Swarms API ```python theme={null} # No API keys per model, no config_list, no cache_seed { "agent_name": "my_agent", "system_prompt": "...", "model_name": "gpt-4.1", "temperature": 0.7, "max_tokens": 2000, "max_loops": 1, } ``` The Swarms API supports 300+ models. See [Available Models](/docs/examples/examples/models-available) for the full list. *** ## Termination Conditions AutoGen uses `is_termination_msg` callbacks to stop conversations. The Swarms API uses `max_loops` to bound execution. ### AutoGen ```python theme={null} def termination_check(msg): return msg.get("content", "").rstrip().endswith("TERMINATE") agent = autogen.UserProxyAgent( name="user", is_termination_msg=termination_check, max_consecutive_auto_reply=10, ) ``` ### Swarms API ```python theme={null} { "swarm_type": "GroupChat", "task": "...", "agents": [...], "max_loops": 5, } ``` *** ## Key Differences to Keep in Mind | Concern | AutoGen | Swarms API | | --------------------- | ----------------------------- | -------------------------------------------------------------------------------------- | | Conversation history | Managed in-memory per session | Stateless; each request is independent | | Human input | `human_input_mode="ALWAYS"` | Not supported in API mode | | Code execution | Docker or local subprocess | Not built in — no sandboxed execution tool is provided | | Function calling | `register_function()` | `tools_list_dictionary` (OpenAI-style function schemas) on the agent | | Nested chats | `register_nested_chats()` | Use `HierarchicalSwarm` or `GraphWorkflow` | | Cost / token tracking | Via OpenAI usage logs | `usage.billing_info.total_cost` (swarm) / `usage.total_cost` (agent) in every response | | Caching | `cache_seed` on `llm_config` | Not applicable; no local cache | *** ## Related Resources * [GroupChat](/docs/documentation/multi-agent/group_chat) * [Debate with Judge](/docs/documentation/multi-agent/debate_with_judge) * [Hierarchical Swarm](/docs/documentation/multi-agent/hierarchical_swarm) * [Migration Overview](/docs/guides/migration/overview) # Migrate from CrewAI Source: https://docs.swarms.ai/docs/guides/migration/from-crewai Side-by-side translation guide for moving CrewAI crews and tasks to the Swarms API CrewAI models multi-agent work as a **Crew** of role-playing Agents executing Tasks under a Process (sequential or hierarchical). The Swarms API maps directly onto this mental model — agents have roles and system prompts, tasks are the top-level input, and processes map to specific workflow types. | CrewAI | Swarms API | | ------------------------------------------- | --------------------------------------------------------------------- | | `Agent(role, goal, backstory, llm)` | `agent` with `agent_name`, `system_prompt`, `model_name` | | `Task(description, agent, expected_output)` | Top-level `task` string; role in `system_prompt` | | `Crew(agents, tasks, process=sequential)` | `SequentialWorkflow` via `/v1/swarm/completions` | | `Crew(agents, tasks, process=hierarchical)` | `HierarchicalSwarm` via `/v1/swarm/completions` | | `crew.kickoff()` | `POST /v1/swarm/completions` | | `crew.kickoff_async()` | Same endpoint; async via `httpx.AsyncClient` | | `@tool` / `BaseTool` | `tools_list_dictionary` (OpenAI-style function schemas) on agent spec | | `manager_llm` | Director agent in `HierarchicalSwarm` | | `memory=True` | Stateless per-request; add external memory for cross-session | | `verbose=True` | Full agent outputs returned in `output` response field | *** ## Side-by-Side: Sequential Crew ```mermaid theme={null} graph LR A([Task Input]) --> B["Senior Research Analyst"] B --> C["Tech Content Strategist"] C --> D([Blog Post Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#065f46,color:#fff ``` ### CrewAI ```python theme={null} from crewai import Agent, Task, Crew, Process from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4.1") researcher = Agent( role="Senior Research Analyst", goal="Uncover cutting-edge developments in AI", backstory="You work at a leading tech think tank with 10 years of experience.", llm=llm, verbose=True, ) writer = Agent( role="Tech Content Strategist", goal="Craft compelling content on tech advancements", backstory="You are a renowned content strategist known for insightful articles.", llm=llm, verbose=True, ) research_task = Task( description="Conduct comprehensive research on the latest AI advancements in 2025.", expected_output="A detailed report with key findings, trends, and implications.", agent=researcher, ) write_task = Task( description="Write an engaging blog post based on the research findings.", expected_output="A 500-word blog post formatted in markdown.", agent=writer, ) crew = Crew( agents=[researcher, writer], tasks=[research_task, write_task], process=Process.sequential, verbose=True, ) result = crew.kickoff() print(result.raw) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "AI Research and Writing Crew", "description": "Research AI advancements then write a blog post", "swarm_type": "SequentialWorkflow", "task": "Research the latest AI advancements in 2025 and write an engaging 500-word blog post.", "agents": [ { "agent_name": "Senior Research Analyst", "system_prompt": ( "You are a Senior Research Analyst at a leading tech think tank with 10 years " "of experience. Your goal is to uncover cutting-edge developments in AI. " "Conduct comprehensive research and return a detailed report with key findings, " "trends, and implications." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Tech Content Strategist", "system_prompt": ( "You are a renowned Tech Content Strategist known for insightful, engaging articles. " "Your goal is to craft compelling content on tech advancements. " "Using the research provided, write a 500-word blog post formatted in markdown." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6, }, ], "max_loops": 1, }, timeout=120, ).json() final_output = result["output"] print(final_output) ``` **What changed:** * `Agent(role, goal, backstory)` → combine into a single `system_prompt` * `Task(description, expected_output)` → merged into `system_prompt` as instructions * `Process.sequential` → `"swarm_type": "SequentialWorkflow"` * `crew.kickoff()` → `POST` request *** ## Side-by-Side: Hierarchical Crew ```mermaid theme={null} graph TD M["Manager LLM\n(HierarchicalSwarm)"] M --> B["Data Analyst"] M --> C["Report Writer"] B --> M C --> M M --> D([Executive Summary]) style M fill:#92400e,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#065f46,color:#fff ``` ### CrewAI ```python theme={null} from crewai import Agent, Task, Crew, Process from langchain_openai import ChatOpenAI manager_llm = ChatOpenAI(model="gpt-4.1") analyst = Agent( role="Data Analyst", goal="Analyze financial data and extract key metrics", backstory="Expert in financial modeling and data interpretation.", llm=ChatOpenAI(model="gpt-4.1"), ) writer = Agent( role="Report Writer", goal="Write clear financial reports", backstory="Specialist in translating complex data into readable reports.", llm=ChatOpenAI(model="gpt-4.1"), ) analysis_task = Task( description="Analyze Q4 2024 earnings data and extract key performance indicators.", expected_output="Structured KPI report with growth metrics.", agent=analyst, ) report_task = Task( description="Write an executive summary report based on the analysis.", expected_output="A 300-word executive summary.", agent=writer, ) crew = Crew( agents=[analyst, writer], tasks=[analysis_task, report_task], process=Process.hierarchical, manager_llm=manager_llm, verbose=True, ) result = crew.kickoff() ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Financial Report Crew", "description": "Hierarchical crew for financial analysis and report writing", "swarm_type": "HierarchicalSwarm", "task": "Analyze Q4 2024 earnings data, extract key KPIs, and write a 300-word executive summary.", "agents": [ { "agent_name": "Data Analyst", "system_prompt": ( "You are an expert Data Analyst specializing in financial modeling. " "Analyze the provided financial data and extract key performance indicators, " "growth metrics, and trends. Return a structured KPI report." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2, }, { "agent_name": "Report Writer", "system_prompt": ( "You are a specialist Report Writer who translates complex financial data into " "clear, readable reports. Using the analysis provided, write a 300-word " "executive summary suitable for C-suite readers." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4, }, ], "max_loops": 1, }, timeout=120, ).json() print(result["output"]) ``` *** ## Side-by-Side: Tool-Using Agent ```mermaid theme={null} graph LR A([Task Input]) --> B["Market Researcher"] B --> T{browser tool} T --> B B --> C([Market Report]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style T fill:#92400e,color:#fff style C fill:#065f46,color:#fff ``` ### CrewAI ```python theme={null} from crewai import Agent, Task, Crew from crewai_tools import SerperDevTool, WebsiteSearchTool search_tool = SerperDevTool() web_tool = WebsiteSearchTool() researcher = Agent( role="Market Researcher", goal="Find latest market data on electric vehicles", backstory="Expert market researcher with access to real-time data.", tools=[search_tool, web_tool], llm=ChatOpenAI(model="gpt-4.1"), ) task = Task( description="Research current EV market trends, top players, and growth forecasts.", expected_output="A market research report with data and sources.", agent=researcher, ) crew = Crew(agents=[researcher], tasks=[task]) result = crew.kickoff() ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "Research the current electric vehicle market trends, top players, and growth forecasts.", "tools_enabled": ["auto_search"], "agent_config": { "agent_name": "Market Researcher", "system_prompt": ( "You are an expert Market Researcher with access to real-time data. " "Research current EV market trends, top players, and growth forecasts. " "Return a comprehensive market research report with data and sources." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, }, timeout=90, ).json() print(result["outputs"]) ``` *** ## Migrating Agent Definitions The most mechanical part of a CrewAI migration is converting `Agent(role, goal, backstory)` to a `system_prompt`. ### CrewAI ```python theme={null} Agent( role="Senior Data Scientist", goal="Build accurate predictive models", backstory="PhD in statistics with 8 years of ML experience at Fortune 500 companies.", llm=ChatOpenAI(model="gpt-4.1"), verbose=True, allow_delegation=False, max_iter=3, ) ``` ### Swarms API ```python theme={null} { "agent_name": "Senior Data Scientist", "system_prompt": ( "You are a Senior Data Scientist with a PhD in statistics and 8 years of ML " "experience at Fortune 500 companies. Your goal is to build accurate predictive " "models. Approach every problem methodically, show your reasoning, and always " "validate your assumptions." ), "model_name": "gpt-4.1", "max_loops": 3, # replaces max_iter "temperature": 0.2, } ``` **Mapping:** * `role` + `goal` + `backstory` → `system_prompt` (combine into natural prose) * `max_iter` → `max_loops` * `allow_delegation=False` → not needed; agents don't self-delegate unless you define edges * `verbose=True` → always on; full outputs are in the response *** ## Migrating Task Definitions ### CrewAI ```python theme={null} Task( description=( "Analyze the provided customer churn dataset. " "Identify the top 5 factors driving churn and estimate their impact." ), expected_output=( "A structured report listing the top 5 churn factors with statistical evidence " "and recommended retention strategies." ), agent=analyst, context=[data_prep_task], ) ``` ### Swarms API ```python theme={null} # task description + expected_output merge into system_prompt. # Context from prior tasks is handled automatically via sequential workflow ordering. { "agent_name": "Churn Analyst", "system_prompt": ( "You are a customer analytics expert. Analyze the provided churn dataset. " "Identify the top 5 factors driving churn with statistical evidence. " "Return a structured report with each factor, its impact estimate, and " "a recommended retention strategy." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.2, } # "task": "Analyze the following churn dataset: ..." ``` *** ## Async Kickoff ### CrewAI ```python theme={null} import asyncio async def run(): result = await crew.kickoff_async() print(result.raw) asyncio.run(run()) ``` ### Swarms API ```python theme={null} import asyncio import httpx import os async def run(): async with httpx.AsyncClient() as client: response = await client.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ ... }, timeout=300, ) result = response.json() print(result["output"]) asyncio.run(run()) ``` *** ## Key Differences to Keep in Mind | Concern | CrewAI | Swarms API | | ------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | Agent memory | `memory=True` per agent | Stateless; use external DB (Redis, Postgres) | | Inter-task context | `context=[task_a, task_b]` | Automatic in sequential workflows; use `edges` in graph workflows | | Human input | `human_input=True` on Task | Not currently supported in API | | Output parsing | `output_pydantic`, `output_json` | Not a dedicated field; instruct the model to return structured JSON via `system_prompt`/`task`, or define a schema in `tools_list_dictionary` | | Rate limiting | Depends on LLM provider | Managed by the API; see [rate limits](/docs/documentation/resources/ratelimits) | | Cost tracking | External | `usage.billing_info.total_cost` (swarm) / `usage.total_cost` (agent) in every response | *** ## Related Resources * [Sequential Workflow](/docs/documentation/multi-agent/sequential_workflow) * [Hierarchical Swarm](/docs/documentation/multi-agent/hierarchical_swarm) * [Agent Completions](/docs/documentation/capabilities/agent) * [Migration Overview](/docs/guides/migration/overview) # Migrate from LangChain Source: https://docs.swarms.ai/docs/guides/migration/from-langchain Side-by-side translation guide for moving LangChain chains, agents, and LCEL pipelines to the Swarms API LangChain provides Python building blocks — `LLMChain`, `AgentExecutor`, LCEL pipes — for constructing AI workflows locally. The Swarms API replaces this entire stack with a single REST endpoint: you describe your agents and workflow in JSON and the API handles orchestration, model routing, retries, and billing. | LangChain | Swarms API | | | -------------------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------- | | `LLMChain(llm, prompt)` | Single agent completion via `/v1/agent/completions` | | | `SequentialChain([chain_a, chain_b])` | `SequentialWorkflow` via `/v1/swarm/completions` | | | `RunnableParallel({a: chain_a, b: chain_b})` | `ConcurrentWorkflow` via `/v1/swarm/completions` | | | `AgentExecutor(agent, tools)` | Agent with `tools_list_dictionary` (custom function schemas) | | | `ChatPromptTemplate.from_messages([...])` | `system_prompt` + `task` fields | | | \`chain\_a | chain\_b\` (LCEL pipe) | `SequentialWorkflow` with agents in order | | `chain.invoke({"input": "..."})` | `POST` request with `"task": "..."` | | | `chain.stream({"input": "..."})` | Same endpoint with `"streaming_on": true` (see [Streaming](/docs/examples/examples/streaming)) | | | `chain.batch([input1, input2])` | `ConcurrentWorkflow` or batch endpoint | | | `ConversationBufferMemory` | Stateless; manage conversation history externally | | | `Tool(name, func, description)` | `tools_list_dictionary` (OpenAI-style function schemas) | | | `ChatOpenAI(model="gpt-4.1")` | `"model_name": "gpt-4.1"` on agent spec | | *** ## Side-by-Side: Simple LLMChain ```mermaid theme={null} graph LR A([Task Input]) --> B[explainer agent] B --> C([Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#065f46,color:#fff ``` ### LangChain ```python theme={null} from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser llm = ChatOpenAI(model="gpt-4.1", temperature=0.5) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant that explains complex topics simply."), ("human", "{topic}"), ]) chain = prompt | llm | StrOutputParser() result = chain.invoke({"topic": "How does transformer attention work?"}) print(result) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "How does transformer attention work?", "agent_config": { "agent_name": "explainer", "system_prompt": "You are a helpful assistant that explains complex topics simply.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5, }, }, timeout=60, ).json() print(result["outputs"]) ``` *** ## Side-by-Side: SequentialChain (LCEL Pipe) ```mermaid theme={null} graph LR A([Task Input]) --> B[Researcher] B -->|findings| C[Summarizer] C --> D([Summary Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#065f46,color:#fff ``` ### LangChain ```python theme={null} from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser llm = ChatOpenAI(model="gpt-4.1") research_prompt = ChatPromptTemplate.from_messages([ ("system", "You are a research specialist. Research the topic thoroughly."), ("human", "Research this topic: {topic}"), ]) summary_prompt = ChatPromptTemplate.from_messages([ ("system", "You are a skilled summarizer. Create a concise summary."), ("human", "Summarize this research:\n\n{research}"), ]) research_chain = research_prompt | llm | StrOutputParser() summary_chain = summary_prompt | llm | StrOutputParser() full_chain = research_chain | (lambda x: {"research": x}) | summary_chain result = full_chain.invoke({"topic": "Quantum computing applications in cryptography"}) print(result) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Research and Summarize", "description": "Research a topic then produce a concise summary", "swarm_type": "SequentialWorkflow", "task": "Research quantum computing applications in cryptography", "agents": [ { "agent_name": "Researcher", "system_prompt": "You are a research specialist. Research the given topic thoroughly and return detailed findings with key facts, current developments, and important context.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "Summarizer", "system_prompt": "You are a skilled summarizer. Read the research provided and produce a clear, concise 3-paragraph summary that captures the essential points.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4, }, ], "max_loops": 1, }, timeout=120, ).json() print(result["output"]) ``` No lambdas or output-passing glue code needed — the sequential workflow passes each agent's output to the next automatically. *** ## Side-by-Side: RunnableParallel ```mermaid theme={null} graph LR A([Task Input]) --> B[pros_analyst] A --> C[cons_analyst] A --> D[examples_analyst] B --> E([outputs]) C --> E D --> E style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#1e40af,color:#fff style E fill:#065f46,color:#fff ``` ### LangChain ```python theme={null} from langchain_core.runnables import RunnableParallel from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser llm = ChatOpenAI(model="gpt-4.1") pros_chain = ( ChatPromptTemplate.from_template("List the pros of {topic}") | llm | StrOutputParser() ) cons_chain = ( ChatPromptTemplate.from_template("List the cons of {topic}") | llm | StrOutputParser() ) examples_chain = ( ChatPromptTemplate.from_template("Give real-world examples of {topic}") | llm | StrOutputParser() ) parallel_chain = RunnableParallel( pros=pros_chain, cons=cons_chain, examples=examples_chain, ) result = parallel_chain.invoke({"topic": "remote work"}) print(result["pros"]) print(result["cons"]) print(result["examples"]) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Parallel Analysis", "description": "Three perspectives on remote work in parallel", "swarm_type": "ConcurrentWorkflow", "task": "Analyze remote work from your specific perspective.", "agents": [ { "agent_name": "pros_analyst", "system_prompt": "You analyze ONLY the pros and benefits of the given topic. List them clearly with brief explanations.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4, }, { "agent_name": "cons_analyst", "system_prompt": "You analyze ONLY the cons and drawbacks of the given topic. List them clearly with brief explanations.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4, }, { "agent_name": "examples_analyst", "system_prompt": "You provide ONLY real-world examples and case studies related to the given topic. Be specific with company names and outcomes.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, ], "max_loops": 1, }, timeout=90, ).json() outputs = result["output"] print(outputs["pros_analyst"]) print(outputs["cons_analyst"]) print(outputs["examples_analyst"]) ``` *** ## Side-by-Side: AgentExecutor with Tools ```mermaid theme={null} graph LR A([Task Input]) --> B[research_assistant] B --> T{browser tool} T --> B B --> C([Answer + Sources]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style T fill:#92400e,color:#fff style C fill:#065f46,color:#fff ``` ### LangChain ```python theme={null} from langchain_openai import ChatOpenAI from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_community.tools.tavily_search import TavilySearchResults from langchain_core.tools import tool llm = ChatOpenAI(model="gpt-4.1", temperature=0) search = TavilySearchResults(max_results=3) @tool def get_word_length(word: str) -> int: """Returns the number of characters in a word.""" return len(word) tools = [search, get_word_length] prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful research assistant."), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) agent = create_openai_tools_agent(llm, tools, prompt) executor = AgentExecutor(agent=agent, tools=tools, verbose=True) result = executor.invoke({"input": "What is the current population of Japan?"}) print(result["output"]) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "What is the current population of Japan?", "tools_enabled": ["auto_search"], "agent_config": { "agent_name": "research_assistant", "system_prompt": "You are a helpful research assistant. Use available tools to find accurate, up-to-date information.", "model_name": "gpt-4.1", "max_loops": 3, "temperature": 0.2, }, }, timeout=90, ).json() print(result["outputs"]) ``` The built-in `tools_enabled` values are currently `auto_search` and `web_scraper`; call `GET /v1/tools/available` to fetch the current list, or attach custom function tools via `tools_list_dictionary`. *** ## Side-by-Side: Streaming ```mermaid theme={null} graph LR A([Task Input]) --> B[storyteller agent] B -->|token stream| C([SSE / chunks]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#065f46,color:#fff ``` ### LangChain ```python theme={null} from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate llm = ChatOpenAI(model="gpt-4.1", streaming=True) prompt = ChatPromptTemplate.from_template("Tell me a short story about {topic}") chain = prompt | llm for chunk in chain.stream({"topic": "a robot learning to paint"}): print(chunk.content, end="", flush=True) ``` ### Swarms API ```python theme={null} import os import requests with requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "Tell me a short story about a robot learning to paint.", "agent_config": { "agent_name": "storyteller", "system_prompt": "You are a creative storyteller.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.7, "streaming_on": True, }, }, stream=True, timeout=120, ) as response: for chunk in response.iter_content(chunk_size=None): print(chunk.decode(), end="", flush=True) ``` See the [Streaming guide](/docs/examples/examples/streaming) for full details. *** ## Prompt Templates → System Prompts LangChain's `ChatPromptTemplate` separates system messages from human messages. In the Swarms API, system instructions go in `system_prompt` and the user's request goes in `task`. ### LangChain ```python theme={null} prompt = ChatPromptTemplate.from_messages([ ("system", "You are an expert {role}. Always respond in {language}."), ("human", "{question}"), ]) chain = prompt | llm | StrOutputParser() result = chain.invoke({ "role": "Python developer", "language": "English", "question": "What is a decorator?", }) ``` ### Swarms API ```python theme={null} result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "What is a decorator?", "agent_config": { "agent_name": "python_expert", "system_prompt": "You are an expert Python developer. Always respond clearly and concisely in English.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, }, timeout=60, ).json() print(result["outputs"]) ``` Variables that were filled in via `ChatPromptTemplate` are simply inlined into the `system_prompt` string. *** ## Structured Output ### LangChain ```python theme={null} from langchain_openai import ChatOpenAI from pydantic import BaseModel, Field class Sentiment(BaseModel): label: str = Field(description="positive, negative, or neutral") score: float = Field(description="confidence score 0-1") reasoning: str = Field(description="brief explanation") llm = ChatOpenAI(model="gpt-4.1") structured_llm = llm.with_structured_output(Sentiment) result = structured_llm.invoke("I absolutely love this product!") print(result.label, result.score) ``` ### Swarms API ```python theme={null} import os, json, requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "Analyze the sentiment of: 'I absolutely love this product!'", "agent_config": { "agent_name": "sentiment_analyzer", "system_prompt": ( "You are a sentiment analysis model. Always respond with valid JSON only, " "in the form {\"label\": ..., \"score\": ..., \"reasoning\": ...}. " "No markdown, no extra text — JSON only." ), "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.1, }, }, timeout=60, ).json() sentiment = json.loads(result["outputs"]) print(sentiment["label"], sentiment["score"]) ``` There is no dedicated `response_format` field on the Swarms API — structured JSON output is achieved by instructing the model in `system_prompt` (as above), then parsing the returned text yourself. *** ## Memory and Conversation History LangChain's `ConversationBufferMemory` persists chat history between chain calls. The Swarms API is stateless — maintain history externally and pass it in the `task` field. ### LangChain ```python theme={null} from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain from langchain_openai import ChatOpenAI memory = ConversationBufferMemory() chain = ConversationChain(llm=ChatOpenAI(model="gpt-4.1"), memory=memory) chain.predict(input="Hi, my name is Alice.") chain.predict(input="What is my name?") ``` ### Swarms API ```python theme={null} import os import requests conversation_history = [] def chat(user_message: str) -> str: conversation_history.append(f"User: {user_message}") context = "\n".join(conversation_history) result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": f"Conversation so far:\n{context}\n\nRespond to the last user message.", "agent_config": { "agent_name": "conversational_agent", "system_prompt": "You are a friendly conversational assistant. Use the conversation history provided to give contextually aware responses.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.5, }, }, timeout=60, ).json() reply = result["outputs"] conversation_history.append(f"Assistant: {reply}") return reply print(chat("Hi, my name is Alice.")) print(chat("What is my name?")) ``` *** ## Key Differences to Keep in Mind | Concern | LangChain | Swarms API | | | ------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------- | | LCEL composition | \`chain\_a | chain\_b\` pipe syntax | `SequentialWorkflow` with agents in order | | Memory | `ConversationBufferMemory`, `VectorStoreRetriever` | Stateless; manage externally | | | Streaming | `.stream()` / `.astream()` | Same endpoint with `"streaming_on": true` on the agent config (SSE response) | | | Callbacks | `callbacks=[...]` on chain/agent | Not needed; all outputs returned in response | | | Retry logic | `with_retry()` | Handled server-side | | | Fallbacks | `with_fallbacks([...])` | `fallback_models` (ordered list) / `fallback_model_name` on the agent spec | | | Output parsers | `StrOutputParser`, `PydanticOutputParser` | No dedicated field; instruct the model via `system_prompt` to emit JSON, then parse it yourself | | | Vector stores / RAG | `VectorStoreRetriever` | Pass retrieved context directly in `task` | | | Embeddings | `OpenAIEmbeddings`, etc. | Not needed in the API; use external embedding service | | *** ## Related Resources * [Sequential Workflow](/docs/documentation/multi-agent/sequential_workflow) * [Concurrent Workflow](/docs/documentation/multi-agent/concurrent_workflow) * [Agent Completions](/docs/documentation/capabilities/agent) * [Streaming](/docs/examples/examples/streaming) * [Structured Outputs](/docs/examples/examples/structured-outputs) * [Migration Overview](/docs/guides/migration/overview) # Migrate from LangGraph Source: https://docs.swarms.ai/docs/guides/migration/from-langgraph Side-by-side translation guide for moving LangGraph StateGraph workflows to the Swarms API Graph Workflow LangGraph lets you define multi-agent workflows as a compiled `StateGraph` where nodes are Python callables and edges define control flow. The Swarms API exposes the same directed-graph model as a REST endpoint — no Python environment required, no graph compilation step, and parallel execution is handled server-side. | LangGraph | Swarms API | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `StateGraph` | `GraphWorkflow` via `/v1/graph-workflow/completions` | | Node (callable / Runnable) | `agent` object in `agents` array | | `graph.add_edge(a, b)` | `{"source": "a", "target": "b"}` in `edges` | | `graph.add_conditional_edges` | Use `MultiAgentRouter` for routing logic | | `graph.set_entry_point(node)` | `"entry_points": ["node_name"]` | | State dict (`TypedDict`) | Outputs from each agent automatically forwarded downstream | | `graph.compile()` | Not needed — configuration is declarative JSON | | `graph.invoke({"messages": [...]})` | `"task": "..."` top-level field in the request body | | `ToolNode` / `bind_tools` | `"tools_enabled": ["auto_search", "web_scraper"]` on the request, or `tools_list_dictionary` on the agent for custom function schemas | *** ## Side-by-Side: Simple Two-Node Chain ```mermaid theme={null} graph LR A([Task Input]) --> B[researcher] B --> C[writer] C --> D([Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#065f46,color:#fff ``` ### LangGraph ```python theme={null} from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from typing import TypedDict llm = ChatOpenAI(model="gpt-4.1") class State(TypedDict): messages: list def researcher(state: State) -> State: response = llm.invoke(state["messages"]) return {"messages": state["messages"] + [response]} def writer(state: State) -> State: response = llm.invoke(state["messages"]) return {"messages": state["messages"] + [response]} graph = StateGraph(State) graph.add_node("researcher", researcher) graph.add_node("writer", writer) graph.add_edge("researcher", "writer") graph.add_edge("writer", END) graph.set_entry_point("researcher") app = graph.compile() result = app.invoke({"messages": [{"role": "user", "content": "Research and write about AI trends"}]}) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/graph-workflow/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Research and Write", "description": "Research a topic then write about it", "task": "Research and write about AI trends", "agents": [ { "agent_name": "researcher", "system_prompt": "You are a research specialist. Investigate the topic thoroughly and return detailed findings.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "writer", "system_prompt": "You are a professional writer. Using the research provided, write an engaging, well-structured article.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.6, }, ], "edges": [ {"source": "researcher", "target": "writer"}, ], "entry_points": ["researcher"], "end_points": ["writer"], "max_loops": 1, }, timeout=120, ).json() print(result["outputs"]["writer"]) ``` *** ## Side-by-Side: Parallel Fan-in Graph The pattern of running multiple nodes in parallel and merging their outputs into a single node is directly supported. ```mermaid theme={null} graph LR A([Task Input]) --> B[tech_researcher] A --> C[market_researcher] B --> D[synthesizer] C --> D D --> E([Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#7c3aed,color:#fff style E fill:#065f46,color:#fff ``` ### LangGraph ```python theme={null} from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from typing import TypedDict, Annotated import operator llm = ChatOpenAI(model="gpt-4.1") class State(TypedDict): topic: str tech_research: str market_research: str final_report: str def tech_researcher(state: State) -> State: result = llm.invoke(f"Research technical aspects of: {state['topic']}") return {"tech_research": result.content} def market_researcher(state: State) -> State: result = llm.invoke(f"Research market trends for: {state['topic']}") return {"market_research": result.content} def synthesizer(state: State) -> State: prompt = f"Synthesize these findings:\nTech: {state['tech_research']}\nMarket: {state['market_research']}" result = llm.invoke(prompt) return {"final_report": result.content} graph = StateGraph(State) graph.add_node("tech_researcher", tech_researcher) graph.add_node("market_researcher", market_researcher) graph.add_node("synthesizer", synthesizer) graph.set_entry_point("tech_researcher") graph.add_edge("tech_researcher", "synthesizer") graph.add_edge("market_researcher", "synthesizer") graph.add_edge("synthesizer", END) # Need to run market_researcher in parallel separately or use Send API app = graph.compile() ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/graph-workflow/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Parallel Research Pipeline", "description": "Two researchers run in parallel, results merge into a synthesizer", "task": "Research and synthesize: The future of autonomous vehicles", "agents": [ { "agent_name": "tech_researcher", "system_prompt": "You are a technical researcher. Investigate engineering, hardware, and software aspects of the topic.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "market_researcher", "system_prompt": "You are a market analyst. Research market size, adoption trends, key players, and business dynamics.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, { "agent_name": "synthesizer", "system_prompt": "You are a strategic analyst. Synthesize technical and market research into a comprehensive, actionable report.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.4, }, ], "edges": [ {"source": "tech_researcher", "target": "synthesizer"}, {"source": "market_researcher", "target": "synthesizer"}, ], "entry_points": ["tech_researcher", "market_researcher"], "end_points": ["synthesizer"], "max_loops": 1, }, timeout=180, ).json() print(result["outputs"]["synthesizer"]) ``` Both `tech_researcher` and `market_researcher` start simultaneously. `synthesizer` receives both outputs before it runs. This is the `Send` API pattern in LangGraph, handled automatically by the Swarms API. *** ## Side-by-Side: Tool-Using Agent ```mermaid theme={null} graph LR A([Task Input]) --> B[news_researcher] B --> T{browser tool} T --> B B --> C([Output]) style A fill:#374151,color:#fff style B fill:#1e40af,color:#fff style T fill:#92400e,color:#fff style C fill:#065f46,color:#fff ``` ### LangGraph ```python theme={null} from langgraph.prebuilt import create_react_agent from langchain_openai import ChatOpenAI from langchain_community.tools.tavily_search import TavilySearchResults llm = ChatOpenAI(model="gpt-4.1") tools = [TavilySearchResults(max_results=3)] agent = create_react_agent(llm, tools) result = agent.invoke({"messages": [{"role": "user", "content": "What are the latest AI news?"}]}) print(result["messages"][-1].content) ``` ### Swarms API ```python theme={null} import os import requests result = requests.post( "https://api.swarms.world/v1/agent/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "task": "What are the latest AI news?", "tools_enabled": ["auto_search"], "agent_config": { "agent_name": "news_researcher", "system_prompt": "You are a research assistant. Search for and summarize the latest AI news.", "model_name": "gpt-4.1", "max_loops": 1, "temperature": 0.3, }, }, timeout=60, ).json() print(result["outputs"]) ``` *** ## Conditional Routing LangGraph's `add_conditional_edges` routes to different nodes based on a function's return value. The Swarms API equivalent is `MultiAgentRouter`, which uses an LLM to intelligently route the task to the most appropriate agent. ```mermaid theme={null} graph LR A([Task Input]) --> R{MultiAgentRouter} R -->|code task| B[code_reviewer] R -->|content task| C[content_writer] B --> D([Output]) C --> D style A fill:#374151,color:#fff style R fill:#92400e,color:#fff style B fill:#1e40af,color:#fff style C fill:#1e40af,color:#fff style D fill:#065f46,color:#fff ``` ### LangGraph ```python theme={null} def route(state: State) -> str: if "code" in state["messages"][-1].content.lower(): return "code_reviewer" return "content_writer" graph.add_conditional_edges("classifier", route, { "code_reviewer": "code_reviewer", "content_writer": "content_writer", }) ``` ### Swarms API ```python theme={null} result = requests.post( "https://api.swarms.world/v1/swarm/completions", headers={"x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json"}, json={ "name": "Smart Router", "description": "Route tasks to the right specialist", "swarm_type": "MultiAgentRouter", "task": "Review this Python function for bugs: def add(a, b): return a - b", "agents": [ { "agent_name": "code_reviewer", "system_prompt": "You are a senior software engineer. Review code for bugs, style, and correctness.", "model_name": "gpt-4.1", "max_loops": 1, }, { "agent_name": "content_writer", "system_prompt": "You are a professional content writer. Write clear, engaging content on any topic.", "model_name": "gpt-4.1", "max_loops": 1, }, ], "max_loops": 1, }, timeout=60, ).json() ``` *** ## State Management In LangGraph you define an explicit `State` TypedDict and every node receives and returns state updates. In the Swarms API, **you don't manage state** — each agent's full output is automatically appended to the context window of all downstream agents via the graph edges. ### LangGraph state pattern ```python theme={null} class State(TypedDict): messages: Annotated[list, operator.add] research_notes: str draft: str final: str def writer(state: State) -> State: # Must explicitly read state["research_notes"] prompt = f"Using these notes: {state['research_notes']}, write a draft." ... return {"draft": result.content} ``` ### Swarms API equivalent ```python theme={null} # No state class needed. # The writer agent's system_prompt tells it what to do with upstream context. { "agent_name": "writer", "system_prompt": ( "You are a professional writer. You will receive research notes from " "upstream agents. Use all of that context to write a polished draft." ), "model_name": "gpt-4.1", "max_loops": 1, } ``` *** ## Key Differences to Keep in Mind | Concern | LangGraph | Swarms API | | ---------------------- | -------------------------------------- | ------------------------------------------------------------------------------------ | | Graph compilation | Required (`graph.compile()`) | Not needed — JSON is declarative | | State persistence | Explicit `TypedDict` with reducers | Outputs automatically forwarded via edges | | Streaming | `astream_events()` | Set `"streaming_on": true` on the agent config (SSE response from the same endpoint) | | Human-in-the-loop | `interrupt_before` / `interrupt_after` | Not currently supported | | Memory / checkpointing | `MemorySaver`, `SqliteSaver` | Stateless per-request; use external DB for cross-request memory | | Local dev | `langgraph dev` server | No local setup; call the REST API directly | *** ## Related Resources * [Graph Workflow Reference](/docs/documentation/multi-agent/graph_workflow) * [Graph Workflow Examples](/docs/examples/examples/graph-workflow) * [MultiAgentRouter](/docs/documentation/multi-agent/multi_agent_router) * [Migration Overview](/docs/guides/migration/overview) # Migration Overview Source: https://docs.swarms.ai/docs/guides/migration/overview Moving from LangGraph, CrewAI, AutoGen, or LangChain to the Swarms API — concept mapping, key differences, and where to start The Swarms API is a **hosted, model-agnostic multi-agent REST API**. Unlike Python-only orchestration frameworks, you call it over HTTP from any language, deploy nothing locally, and pay only for what you run. It handles all agent scheduling, context passing, parallel execution, and retries on its side. | Capability | LangGraph | CrewAI | AutoGen | LangChain | Swarms API | | ---------------- | ----------------------- | ------------------------- | ----------------------- | ----------------------- | ------------------------- | | Deployment | Self-hosted | Self-hosted | Self-hosted | Self-hosted | Fully hosted | | Language | Python | Python | Python | Python / JS | Any (REST) | | Multi-agent | Graph DAG | Sequential / Hierarchical | GroupChat | Chains / Agents | 10+ architectures | | State management | Explicit state graph | Task-based | Conversation history | Memory modules | Handled by API | | Parallelism | Async / compiled graph | Limited | GroupChat turns | Limited | Native parallel execution | | Model support | OpenAI, Anthropic, etc. | OpenAI, Anthropic, etc. | OpenAI, Anthropic, etc. | 100+ via LiteLLM | 300+ via unified endpoint | | Pricing | Infra cost + model cost | Infra cost + model cost | Infra cost + model cost | Infra cost + model cost | Per-token + per-agent | *** ## Concept Mapping The table below maps every major concept from each framework to its Swarms API equivalent. ### Agents | Framework | Their Concept | Swarms API Equivalent | | --------- | ------------------------------------- | ----------------------------------------------- | | LangGraph | `node` (a callable or Runnable) | `agent` object in `agents` array | | CrewAI | `Agent(role, goal, backstory)` | `agent` with `agent_name` + `system_prompt` | | AutoGen | `AssistantAgent` / `ConversableAgent` | `agent` with `system_prompt` | | LangChain | `AgentExecutor` / `LLMChain` | Single agent completion or `SequentialWorkflow` | ### Workflows & Orchestration | Framework | Their Concept | Swarms API Equivalent | | --------- | ------------------------------------ | ---------------------------------------------------------- | | LangGraph | `StateGraph` with conditional edges | `GraphWorkflow` with `edges`, `entry_points`, `end_points` | | CrewAI | `Crew(process=Process.sequential)` | `SequentialWorkflow` | | CrewAI | `Crew(process=Process.hierarchical)` | `HierarchicalSwarm` | | AutoGen | `GroupChat` + `GroupChatManager` | `GroupChat` swarm type | | LangChain | `SequentialChain` | `SequentialWorkflow` | | LangChain | Parallel `RunnableParallel` | `ConcurrentWorkflow` | ### Tasks & Prompts | Framework | Their Concept | Swarms API Equivalent | | --------- | ------------------------------------------- | -------------------------------------------------------------- | | LangGraph | State dict passed between nodes | Agent output is appended to context automatically | | CrewAI | `Task(description, agent, expected_output)` | Top-level `task` string; agent role defined in `system_prompt` | | AutoGen | `initiate_chat(message)` | Top-level `task` string | | LangChain | `PromptTemplate` + `chain.invoke(input)` | `system_prompt` + `task` | ### Tools | Framework | Their Concept | Swarms API Equivalent | | --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | LangGraph | `ToolNode` / `bind_tools` | `tools_enabled` array on the request (e.g. `"auto_search"`, `"web_scraper"`), or custom function schemas via `tools_list_dictionary` | | CrewAI | `@tool` decorated functions | `tools_list_dictionary` (OpenAI-style function schemas) on the agent | | AutoGen | `register_function` | `tools_list_dictionary` (OpenAI-style function schemas) on the agent | | LangChain | `Tool` / `BaseTool` | `tools_list_dictionary` (OpenAI-style function schemas) on the agent | *** ## Architecture Selection Guide Once you know what you were building in your old framework, use this table to pick the right Swarms workflow: | What you were building | Best Swarms architecture | | --------------------------------------- | ------------------------ | | Linear pipeline (A → B → C) | `SequentialWorkflow` | | Parallel fan-out (all agents same task) | `ConcurrentWorkflow` | | Graph with mixed parallel + sequential | `GraphWorkflow` | | Hierarchical with a manager agent | `HierarchicalSwarm` | | Route tasks to the right specialist | `MultiAgentRouter` | | Multiple experts debate and consensus | `MajorityVoting` | | Open-ended group discussion | `GroupChat` | | Compare N approaches to same problem | `MixtureOfAgents` | | Same tasks × multiple agents (grid) | `BatchedGridWorkflow` | *** ## Universal Migration Checklist Regardless of which framework you are migrating from, follow these steps: 1. **Get your API key** at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. **Set the environment variable**: `export SWARMS_API_KEY="your-key"` 3. **Install the HTTP client** of your choice (`requests`, `httpx`, `fetch`, `axios`, etc.) 4. **Map each agent** in your old workflow to an `agent` object with `agent_name`, `system_prompt`, and `model_name` 5. **Map the topology** — sequential chain, parallel fan-out, or directed graph 6. **Replace `task` inputs** — the top-level `task` field replaces all `invoke()`, `kickoff()`, and `initiate_chat()` calls 7. **Remove local infrastructure** — no more Python environments, LLM SDK imports, or API key plumbing per-library *** ## Migration Guides Choose your current framework: * [Migrate from LangGraph](/docs/guides/migration/from-langgraph) * [Migrate from CrewAI](/docs/guides/migration/from-crewai) * [Migrate from AutoGen](/docs/guides/migration/from-autogen) * [Migrate from LangChain](/docs/guides/migration/from-langchain) *** ## Quick Start After Migration Every Swarms API call follows the same pattern regardless of workflow type: ```python theme={null} import os import requests response = requests.post( "https://api.swarms.world/v1/<workflow-endpoint>/completions", headers={ "x-api-key": os.environ["SWARMS_API_KEY"], "Content-Type": "application/json", }, json={ "name": "My Workflow", "description": "What this workflow does", "task": "The task to complete", "agents": [ ... ], # your agents here # workflow-specific fields (edges, entry_points, etc.) }, timeout=300, ) result = response.json() ``` The base URL is `https://api.swarms.world`. See the [API Reference](/docs/documentation/index) for all available endpoints. # Hiring Source: https://docs.swarms.ai/docs/introduction/hiring Help us build the agent economy. We are hiring talented individuals who are passionate about AI, agents, and creating the future of work. Why join our team? We are devoted to the mission above all else: building the agent economy and unlocking unimaginable prosperity for humanity. We bring relentless dedication to solving the most challenging problems in AI and agent systems. Most importantly, everyone who works here finds fulfillment in their work—knowing that every line of code, every feature, and every decision moves us closer to a world where autonomous agents transform how work gets done and amplify human potential. **[View Open Positions & Apply →](https://www.swarms.ai/hiring)** *** *Building the agent economy, together. [The Swarm Corporation](https://swarms.ai)* # Links and Resources Source: https://docs.swarms.ai/docs/introduction/links-and-resources All social media links, website links, and resources for The Swarm Corporation Find all our social media profiles, website links, support resources, and important URLs in one place. ## Social Media | Platform | Link | Description | | ------------ | --------------------------------------------------------------------------------- | ------------------------------------------------ | | **Twitter** | [@swarms\_corp](https://twitter.com/swarms_corp) | Follow us for updates, announcements, and news | | **GitHub** | [The-Swarm-Corporation](https://github.com/The-Swarm-Corporation/swarms-api-docs) | View our documentation repository and contribute | | **LinkedIn** | [The Swarm Corporation](https://www.linkedin.com/company/the-swarm-corporation) | Connect with us on LinkedIn | | **Discord** | [Join Discord](https://discord.gg/EamjgSaEQf) | Join our community Discord server | | **YouTube** | [Swarms Channel](https://www.youtube.com/channel/UC9yXyitkbU_WSy7bd_41SqQ) | Watch tutorials, demos, and updates | | **Medium** | [@kyeg](https://medium.com/@kyeg) | Read our blog posts and articles | ## Website Links | Resource | Link | Description | | ---------------------- | ---------------------------------------------------------- | ------------------------------------- | | **Main Website** | [swarms.ai](https://swarms.ai) | The Swarm Corporation homepage | | **Documentation** | [docs.swarms.ai](https://docs.swarms.ai) | Complete API documentation and guides | | **Platform Dashboard** | [swarms.world](https://swarms.world) | Access the Swarms platform | | **API Keys** | [Get API Key](https://swarms.world/platform/api-keys) | Get your API key to start building | | **Account Management** | [Account Dashboard](https://swarms.world/platform/account) | Manage your account and settings | ## Support & Resources | Resource | Link | Description | | --------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------- | | **Status Page** | [status.swarms.ai](https://status.swarms.ai) | Check service status and uptime | | **Technical Support** | [Schedule Support](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) | Book a technical support session | | **Discord Community** | [Join Discord](https://discord.gg/EamjgSaEQf) | Get help from the community | | **Client Libraries** | [Client Libraries](https://docs.swarms.ai/docs/documentation/resources/client-libraries) | Official client libraries and SDKs | ## API Resources | Resource | Link | Description | | ------------------------- | ---------------------------------------------------------------------- | ------------------------------ | | **API Base URL** | [api.swarms.world](https://api.swarms.world) | Base URL for all API requests | | **OpenAPI Specification** | [OpenAPI JSON](https://api.swarms.world/openapi.json) | Complete OpenAPI specification | | **API Reference** | [API Reference](https://docs.swarms.ai/api-reference/general/api-root) | Interactive API documentation | ## Quick Links <CardGroup> <Card title="Get API Key" icon="key" href="https://swarms.world/platform/api-keys"> Get your API key to start building with Swarms API. </Card> <Card title="Join Discord" icon="message-circle" href="https://discord.gg/EamjgSaEQf"> Join our community Discord for support and discussions. </Card> <Card title="Technical Support" icon="headset" href="https://cal.com/swarms/swarms-technical-support?overlayCalendar=true"> Schedule a technical support session. </Card> </CardGroup> # Our Mission Source: https://docs.swarms.ai/docs/introduction/our-mission Building the infrastructure for the agent economy enabling autonomous AI agents to transform how we work, create, and solve problems At The Swarm Corporation, our mission is to build the infrastructure for the agent economy such as the foundational systems, protocols, and tools that enable autonomous AI agents to transform how we work, create, and solve problems. The agent economy is not about individual AI assistants; it is about creating an ecosystem where autonomous agents collaborate, coordinate, and participate in economic transactions at scale. We envision a future where agents handle routine work and complex multi-agent coordination, freeing humans to focus on creative, strategic, and high-value activities. This infrastructure must be robust, performant, and designed to support real-time processing, high throughput, usage-based pricing, and automatic settlement—enabling agents to operate autonomously in economic transactions. Through Swarms API, we provide the orchestration and execution platform for building multi-agent systems at any scale, enabling hierarchical, sequential, and parallel agent workflows that coordinate seamlessly. This forms the foundation for a world where agents operate autonomously, participate in markets, and collaborate to solve previously intractable problems. We are building the foundation for a future where human and agent work becomes seamless, where agents augment human capabilities, and where the agent economy creates new opportunities for innovation and growth. # Our Products Source: https://docs.swarms.ai/docs/introduction/our-products Explore Swarms API and Swarms Marketplace - the infrastructure powering the agent economy The Swarm Corporation provides two core products: > **Swarms API** for building multi-agent systems > **Swarms Marketplace** for discovering, creating, and monetizing agents and prompts. ## Swarms API Build and orchestrate multi-agent systems at scale. From single agents to thousands in complex workflows. <CardGroup> <Card title="Multi-Agent Orchestration" icon="layers" href="/docs/documentation/multi-agent/swarm_types"> Build hierarchical, sequential, and parallel agent systems at scale. </Card> <Card title="Agent Communication" icon="message-square" href="/docs/documentation/multi-agent/best_practices"> Seamless coordination and knowledge sharing across agents. </Card> <Card title="Optimized Runtime" icon="cpu" href="/docs/documentation/getting-started/architecture"> High-performance, concurrent runtime for resource efficiency. </Card> <Card title="Conversation History" icon="database" href="/docs/documentation/capabilities/agent"> Maintain context across multiple interactions in complex workflows. </Card> </CardGroup> <CardGroup> <Card title="Quickstart" icon="rocket" href="/docs/documentation/getting-started/quickstart"> Build your first agent in under 5 minutes. </Card> <Card title="API Reference" icon="book-open" href="https://api.swarms.world/openapi.json"> Complete OpenAPI specification. </Card> <Card title="Examples" icon="code" href="/docs/examples/examples/agent-overview"> Explore practical examples. </Card> </CardGroup> **[Explore Swarms API Documentation →](/docs/documentation/index)** *** ## Swarms Marketplace Discover, create, and monetize AI agents and prompts in a thriving ecosystem. Publish your creations, find solutions built by others, and participate in the agent economy through multiple monetization models. <CardGroup> <Card title="Agents & Prompts" icon="package" href="/docs/marketplace/agents-vs-prompts"> Publish executable agents or prompt templates for the community. </Card> <Card title="Monetization" icon="dollar-sign" href="/docs/marketplace/tokenization"> Choose from free, paid, or tokenization models for your products. </Card> <Card title="Agents API" icon="code" href="/docs/marketplace/agents-api"> Create, update, and query agents programmatically. </Card> <Card title="Prompts API" icon="file-text" href="/docs/marketplace/prompts-api"> Manage and discover prompt templates via API. </Card> </CardGroup> <CardGroup> <Card title="Getting Started" icon="rocket" href="/docs/marketplace/agents-api"> Start publishing your first agent or prompt. </Card> <Card title="Examples" icon="code" href="/docs/marketplace/examples"> See how others are using the marketplace. </Card> <Card title="Launch Checklist" icon="check-circle" href="/docs/marketplace/launch-checklist"> Ensure your product is ready for launch. </Card> </CardGroup> **[Explore Swarms Marketplace Documentation →](/docs/marketplace/agents-api)** *** ## Getting Started <CardGroup> <Card title="Build Agents" icon="rocket" href="/docs/documentation/getting-started/quickstart"> Start with Swarms API to build and deploy agents. </Card> <Card title="Join Marketplace" icon="store" href="/docs/marketplace/agents-api"> Discover and monetize agents in the marketplace. </Card> </CardGroup> # Introduction Source: https://docs.swarms.ai/docs/introduction/overview Welcome to The Swarm Corporation - Building the infrastructure for the agent economy Welcome to Swarms. Swarms is building production-grade infrastructure for the agent economy, the core systems, protocols, and tools that enable autonomous AI agents to work independently, collaborate with one another, and participate in real economic activity at scale. As work shifts from isolated AI tools to coordinated networks of intelligent agents, Swarms provides a comprehensive platform to build, deploy, and scale these systems reliably in real-world environments. Creating production-ready agent systems is hard, requiring robust orchestration, high-performance runtimes, seamless communication, and real-time payment infrastructure. Swarms delivers a complete, integrated stack: multi-agent orchestration for hierarchical, parallel, and collaborative workflows; a high-efficiency runtime optimized for concurrency; built-in economic infrastructure for usage-based transactions; and developer-friendly APIs that abstract away complexity. Swarms gives you everything needed to move agent systems from prototype to production. ## Our Mission At The Swarm Corporation, we're creating the infrastructure layer that powers the agent economy. We provide the tools, protocols, and platforms that enable developers to build, deploy, and scale intelligent AI systems that can collaborate, reason, and solve complex problems together. Learn more about our mission here: <CardGroup> <Card title="Our Mission" icon="users" href="/docs/introduction/our-mission"> Learn about The Swarm Corporation and our vision for the agent economy. </Card> </CardGroup> ## Products Ready to start building? Choose your path: <CardGroup> <Card title="Build with Swarms API" icon="rocket" href="/docs/documentation/getting-started/quickstart"> Create your first agent in minutes with our comprehensive API platform. </Card> <Card title="Swarms Marketplace" icon="store" href="/docs/marketplace/overview"> Discover, create, and monetize AI agents and prompts in our marketplace. </Card> </CardGroup> *** *Building the agent economy, one agent at a time. [The Swarm Corporation](https://swarms.ai)* # Account Management Source: https://docs.swarms.ai/docs/marketplace/account_management Manage account settings, profile data, billing, subscriptions, and wallet details on Swarms. This guide provides comprehensive, production-grade documentation for managing your account on the Swarms Platform. It covers account settings, profile management, billing, payment methods, subscription details, and cryptocurrency wallet management. Use this documentation to navigate the account management interface, understand available options, and perform account-related operations efficiently and securely. *** ## Table of Contents 1. [Overview](#overview) 2. [Accessing the Account Management Page](#accessing-the-account-management-page) 3. [Account Settings](#account-settings) * [Theme Mode](#theme-mode) 4. [Profile Management](#profile-management) * [Profile Information](#profile-information) * [Password Management](#password-management) 5. [Billing and Payment Methods](#billing-and-payment-methods) * [Subscription Status](#subscription-status) * [Payment Methods](#payment-methods) 6. [Cryptocurrency Wallet](#cryptocurrency-wallet) * [Wallet Overview](#wallet-overview) * [Exchange and Transaction History](#exchange-and-transaction-history) 7. [Additional Resources](#additional-resources) *** ## Overview The Swarms Platform account management page, available at [https://swarms.world/platform/account](https://swarms.world/platform/account), allows you to configure and update your account settings and preferences. From here, you can manage the appearance of the platform, view and update profile details, manage your billing information and subscriptions, and handle your cryptocurrency wallet operations. *** ## Accessing the Account Management Page To access your account management dashboard: 1. Log in to your Swarms Platform account. 2. Navigate to [https://swarms.world/platform/account](https://swarms.world/platform/account). Once on this page, you will see several sections dedicated to different aspects of your account: * **Account Settings:** Customize the platform appearance and user interface. * **Profile:** View and manage personal details. * **Billing:** Review credits, invoices, and manage your payment methods. * **Crypto:** Manage your cryptocurrency wallet and transactions. *** ## Account Settings This section allows you to modify your personal account preferences, including the visual theme. ### Theme Mode You can choose between different theme options to tailor your user experience: * **Single Theme:**\ A fixed theme, independent of system settings. * **Example:** * **Logo:** Swarms logo * **Terminal Command:** ```bash theme={null} pip3 install -U swarms ``` * **Theme Options:** * **light** * **dark (default)** * **Sync with System Theme:**\ Automatically adjusts the platform theme to match your system's theme settings. Select the theme mode that best fits your workflow. Changes are applied immediately across the platform. *** ## Profile Management ### Profile Information The Profile section allows you to view and update your personal details: * **View Details:**\ Your current profile information is displayed, including contact details, username, and any additional settings. * **Manage Profile:**\ Options to update your information, ensuring your account details remain current. ### Password Management For security purposes, it is important to regularly update your password: * **Change Password:**\ Select the **"Change password"** option to update your login credentials.\ Ensure you choose a strong password and keep it confidential. *** ## Billing and Payment Methods The Billing section helps you manage financial aspects of your account, including credits, invoices, and subscriptions. ### Subscription Status Your subscription details are clearly displayed: * **Current Plan:**\ Options include **Free**, **Pro**, or **Premium**. * **Status:**\ The active subscription status is indicated (e.g., "Active"). * **Customer Portal:**\ An option to open the customer portal for additional billing and subscription management. ### Payment Methods Manage your payment methods and review your billing details: * **Manage Cards:**\ View existing payment methods.\ **Example Entry:** * **Card Type:** mastercard * **Last 4 Digits:** ending in 9491 * **Expiry Date:** 2030/2 * **Add Card:**\ Use the **"Add Card"** option to register a new payment method securely. ### Credit System Details of the credits available for your account: * **Credits Available:**\ Displays the current credit balance (e.g., `$20.00`). * **Charge:**\ Option to apply charges against your available credits. * **Invoice:**\ Review or download your invoices. *** ## Cryptocurrency Wallet The Crypto section provides management tools for your cryptocurrency wallet and associated transactions. ### Wallet Overview * **Connected Wallet:**\ Displays your linked wallet information. * **Example:** * **Wallet Identifier:** A truncated wallet ID (e.g., `EmVa...79Vb`) * **\$swarms Balance and Price:** * **Balance:**\ Displays your current \$swarms balance (e.g., `0.00`). * **Price:**\ Current market price for $swarms (e.g., `$0.0400\`). ### Exchange and Transaction History * **Exchange Functionality:**\ Option to exchange \$swarms tokens for credits directly through the platform. * **Transaction History:**\ View a detailed log of wallet transactions, ensuring full transparency over all exchanges and wallet activity. *** ## Additional Resources For further assistance or to learn more about managing your account on the Swarms Platform, refer to the following resources: * [Support](https://swarms.world/support) * [Customer Support](https://cal.com/swarms) * [API Documentation](https://swarms.world/platform/api-keys) (for developers) *** ## Best Practices * **Regular Updates:**\ Periodically review your account settings, profile, and payment methods to ensure they are up-to-date. * **Security Measures:**\ Always use strong, unique passwords and consider enabling two-factor authentication if available. * **Monitor Transactions:**\ Regularly check your billing and wallet transaction history to detect any unauthorized activities promptly. # ACM Hackathon Source: https://docs.swarms.ai/docs/marketplace/acm-hackathon Build, tokenize, and list agents or prompts on the Swarms Marketplace for a chance to earn ACM Hackathon rewards. The ACM Hackathon is live, with **\$30,000 in rewards** available for builders who launch tokenized agents and prompts on the Swarms Marketplace. The hackathon runs from **May 6, 2026** through **May 27, 2026**. To qualify, builders must use Frenzy Mode, tokenize their submission, and publish it for sale on the marketplace. Rewards will be distributed in **Solana, \$SWARMS, and USDC**. [Launch your tokenized prompt or agent](https://swarms.world/launch?type=prompt\&model=tokenized\&frenzy=true) *** ## Overview The ACM Hackathon is designed for builders creating useful, market-ready agents and prompts. Submissions should solve practical problems, be easy for buyers to understand, and show clear value in real-world workflows. Eligible submissions must be tokenized through Frenzy Mode and listed for sale on the Swarms Marketplace before the hackathon ends. *** ## Hackathon Details * **Reward pool:** \$30,000 * **Start date:** May 6, 2026 * **End date:** May 27, 2026 * **Reward currencies:** Solana, \$SWARMS, and USDC * **Eligible submissions:** Tokenized agents and tokenized prompts published for sale on the Swarms Marketplace * **Launch page:** [https://swarms.world/launch?type=prompt\&model=tokenized\&frenzy=true](https://swarms.world/launch?type=prompt\&model=tokenized\&frenzy=true) *** ## Rewards Overview The ACM Hackathon reward pool is split between top-performing builders and active marketplace participants. Half of the prize pool, **\$15,000**, is allocated to the top three winners based on the performance, quality, and impact of their submissions: * **1st place:** \$7,500 * **2nd place:** \$4,500 * **3rd place:** \$3,000 The remaining **\$15,000** will be distributed randomly among eligible participants who successfully launch and publish agents on the Swarms Marketplace. This structure gives strong builders a path to compete for top prizes while ensuring that active participants who contribute meaningful work also have a chance to be rewarded. All rewards will be distributed in **Solana, \$SWARMS, and USDC**. *** ## How to Participate 1. Build an agent or prompt with clear real-world utility. 2. Enable Frenzy Mode during launch to tokenize your submission. 3. Publish the tokenized agent or prompt on the Swarms Marketplace. 4. List it for sale before **May 27, 2026** to qualify for rewards. Launch here: [https://swarms.world/launch?type=prompt\&model=tokenized\&frenzy=true](https://swarms.world/launch?type=prompt\&model=tokenized\&frenzy=true) *** ## What to Build You can submit any agent or prompt that delivers clear utility. Strong submissions may focus on: * Finance and market analysis * Business automation * Research and data synthesis * Creative production * Developer tools * Operations and productivity * Customer support * Sales and marketing workflows These categories are examples, not restrictions. Builders are encouraged to create high-quality products that can attract real users and buyers on the marketplace. *** ## Winner Criteria Top winners will be selected based on the quality, utility, adoption, and market performance of their tokenized agents or prompts. Successful submissions should be useful, well-described, easy to evaluate, and clearly positioned for marketplace buyers. *** ## FAQ <AccordionGroup> <Accordion title="Where can I get support?"> 24/7 support is available at [swarms.world/support](https://swarms.world/support). </Accordion> <Accordion title="How can I connect with the Swarms team and other builders?"> Join the Swarms Discord for real-time communication: [https://discord.gg/VK9jp9sXwJ](https://discord.gg/VK9jp9sXwJ) </Accordion> <Accordion title="How are rewards distributed?"> Rewards are sent directly to the creator addresses associated with eligible tokenized submissions. </Accordion> <Accordion title="When does the hackathon end?"> The hackathon ends on **May 27, 2026**. </Accordion> <Accordion title="What can I build?"> You can build any agent or prompt with real-world utility, including tools for finance, automation, research, creative work, operations, analytics, or developer productivity. </Accordion> <Accordion title="Do I need to tokenize my agent?"> Yes. Tokenization through Frenzy Mode is required to qualify for rewards. </Accordion> <Accordion title="Do I need to list it for sale?"> Yes. Your agent or prompt must be published and available for sale on the Swarms Marketplace. </Accordion> <Accordion title="What determines the winners?"> Winners are determined by the quality, utility, adoption, impact, and market performance of each eligible submission. </Accordion> <Accordion title="Can I submit multiple agents?"> Yes. You can submit multiple agents or prompts as long as each submission meets the eligibility requirements. </Accordion> <Accordion title="What chains or currencies are supported?"> Rewards are distributed in Solana, \$SWARMS, and USDC. </Accordion> <Accordion title="Where do I publish my agent?"> Publish your agent or prompt on the Swarms Marketplace at [swarms.world](https://swarms.world). </Accordion> </AccordionGroup> # Agents API Source: https://docs.swarms.ai/docs/marketplace/agents-api Easily create, update, and fetch agents in the Swarms marketplace in just 3 steps Managing AI agents in the Swarms marketplace is simple—just follow **3 easy steps**: 1. **Authenticate**: Secure your requests with an API key or Supabase session token. 2. **Create, Update, or Query Agents**: Use the endpoints below to add, modify, or search agents. 3. **Get Results or Listings**: Instantly receive confirmation, your agent listing URL, or search results. *** ## Step 1: Authentication All agent management actions require authentication using one of these methods: * **API Key**: Send your API key in the `Authorization` header as `Bearer <your-api-key>`. * **Supabase Session**: Provide your Supabase session token in the `Authorization` header. ## Base URL ``` https://swarms.world ``` *** ## Step 2: Create an Agent It's quick and easy to create your own agent in the marketplace. ### Endpoint ``` POST /api/add-agent ``` ### Input schema (Add Agent) | Parameter | Type | Required | Description | | ----------------------- | ------- | ------------ | ---------------------------------------------------------------------------------------------- | | `name` | string | Yes | Display name (min 2 characters) | | `agent` | string | No | Agent code/content (min 5 characters if provided); can be null | | `language` | string | No | Programming or script language | | `description` | string | Yes | Description of the agent | | `requirements` | array | No | Dependencies; each `{ "package": string, "installation": string }` | | `useCases` | array | No | Use cases; each `{ "title": string, "description": string }` | | `tags` | string | No | Comma-separated tags (min 2 characters if provided) | | `is_free` | boolean | No | Default `true` | | `price_usd` | number | If paid | Required when `is_free` is false; must be > 0 | | `category` | string | No | Optional category | | `status` | string | No | `'pending'` \| `'approved'` \| `'rejected'`; default `'pending'` | | `tokenized_on` | boolean | No | Enable tokenization on Solana | | `ticker` | string | If tokenized | Required when `tokenized_on` is true; uppercase alphanumeric; max 10 characters | | `image_url` | string | No | Public image URL (valid URL or empty string) | | `file_path` | string | No | Storage path for image (alternative to `image_url`) | | `image_base64` | string | No | Base64-encoded image (alternative to `image_url`; may include `data:image/...;base64,` prefix) | | `links` | array | No | Array of strings or `{ "name": string, "url": string }` | | `seller_wallet_address` | string | No | Seller wallet address | | `payment_method` | string | No | `'crypto'` \| `'stripe'`; defaults to `'crypto'` | | `x402_url` | string | No | x402 payment URL (valid URL or empty string) | | `mcp_url` | string | No | MCP server URL (valid URL or empty string) | | `creator_wallet` | string | If tokenized | Creator wallet public key; required when `tokenized_on` is true | | `private_key` | string | If tokenized | Private key for signing (JSON array or base64); required when `tokenized_on` is true | | `fee_selection` | string | No | `'frenzy'` \| `'market'`; fee mode for the token launch | | `quote_mint` | string | No | `'SOL'` \| `'USDC'`; quote currency for the bonding curve (default `SOL`) | | `vault_mode` | boolean | No | Holders-only view gating (requires `tokenized_on`) | ### Request Body (detailed) Just provide the necessary agent details: <ParamField type="string"> The name of the agent (minimum 2 characters) </ParamField> <ParamField type="string"> Agent code/content (minimum 5 characters if provided); can be null </ParamField> <ParamField type="string"> A detailed description of what the agent does </ParamField> <ParamField type="string"> Programming language used (e.g., "python", "javascript") </ParamField> <ParamField type="array"> An array of package requirements ```json theme={null} [ { "package": "pandas", "installation": "pip install pandas" } ] ``` </ParamField> <ParamField type="array"> An array of use cases showing what your agent can do ```json theme={null} [ { "title": "Data Analysis", "description": "Analyze large datasets and generate insights" } ] ``` </ParamField> <ParamField type="string"> Comma-separated tags (minimum 2 characters if provided) </ParamField> <ParamField type="boolean"> Whether the agent is free or paid </ParamField> <ParamField type="number"> Price in USD (required if `is_free` is false, minimum: 0.01) </ParamField> <ParamField type="string"> The agent's category (e.g., "data-science", "automation") </ParamField> <ParamField type="string"> The status of the agent (pending, approved, rejected) </ParamField> <ParamField type="string"> Public image URL (valid URL or empty string) </ParamField> <ParamField type="string"> Storage path for image (alternative to `image_url`) </ParamField> <ParamField type="string"> Base64-encoded image (alternative to `image_url`; can include `data:image/...;base64,` prefix) </ParamField> <ParamField type="array"> Links: array of strings or `{ "name": string, "url": string }` (e.g. website, twitter, telegram for token metadata) </ParamField> <ParamField type="string"> Seller wallet address </ParamField> <ParamField type="string"> x402 payment URL (valid URL or empty string) </ParamField> <ParamField type="string"> MCP server URL (valid URL or empty string) </ParamField> <ParamField type="boolean"> Enable tokenization on Solana </ParamField> <ParamField type="string"> Required when `tokenized_on` is true; uppercase letters and numbers only; max 10 characters </ParamField> <ParamField type="string"> Creator wallet public key; required when `tokenized_on` is true </ParamField> <ParamField type="string"> Private key for signing (JSON array or base64); required when `tokenized_on` is true </ParamField> ### Validation rules * **Paid agents**: When `is_free` is `false`, `price_usd` is required and must be > 0. * **Tokenization**: When `tokenized_on` is `true`, `ticker`, `creator_wallet`, and `private_key` are required; ticker must be uppercase alphanumeric, max 10 characters. * **Duplicate**: Same name and same `agent` content for the same user returns 400 with `existingId`. ### Success response (200) On success, you'll immediately get: ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000", "tokenized": false, "token_address": null, "pool_address": null } ``` When tokenization is used, `tokenized` is `true` and `token_address` and `pool_address` are set. ### Output schema (Add Agent — success) | Field | Type | Description | | --------------- | -------------- | ----------------------------------------------------------------- | | `success` | boolean | `true` on success | | `id` | string | UUID of the created agent | | `listing_url` | string | URL to the agent listing (e.g. `https://swarms.world/agent/{id}`) | | `tokenized` | boolean | Whether the agent was tokenized | | `token_address` | string \| null | Solana token address (when tokenized) | | `pool_address` | string \| null | Liquidity pool address (when tokenized) | ### Error responses (Add Agent) * **400** – Validation: `error`, `message`, `details`, `errors`, `status_code`. Content validation: also `trustworthiness`, `contentQuality`. Duplicate agent: `existingId`. Tokenization failed: standard 400 shape. * **401** – `error`, `message`, `details`, `how_to_get_key`, `status_code`. * **429** – `error`, `message`, `details`, `currentUsage`, `limits`, `resetTime`, `status_code`. * **500** – Server/database/price conversion/tokenization error: `error`, `message`, `details`, `status_code` (may include `hint`, `code` for DB errors). ### Error output schema (common fields) | HTTP | Field | Type | Description | | ---- | ----------------- | ------ | ------------------------------------------------------------------- | | All | `error` | string | Short error message | | All | `message` | string | Detailed description | | All | `code` | string | Error code (e.g. `VALIDATION_ERROR`) | | All | `details` | string | Optional extra context | | All | `status_code` | number | HTTP status code | | 400 | `errors` | object | Validation errors by field | | 400 | `existingId` | string | Existing agent ID (duplicate) | | 400 | `trustworthiness` | number | Content trust score (content validation) | | 400 | `contentQuality` | number | Content quality score (content validation) | | 401 | `how_to_get_key` | string | Instructions to obtain API key | | 429 | `currentUsage` | object | Current usage counts | | 429 | `limits` | object | Rate limit values | | 429 | `resetTime` | string | ISO timestamp when limit resets | | 500 | `hint` | string | Optional DB/system hint (DB errors may also include a `code` field) | ### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/add-agent \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Data Analysis Agent", "agent": "from swarms import Agent\n\nclass DataAnalysisAgent(Agent):\n def analyze(self, data):\n # Analysis logic here\n pass", "description": "An AI agent specialized in analyzing large datasets and generating actionable insights", "language": "python", "requirements": [ { "package": "pandas", "installation": "pip install pandas" }, { "package": "numpy", "installation": "pip install numpy" } ], "useCases": [ { "title": "Financial Data Analysis", "description": "Analyze financial statements and market trends" }, { "title": "Customer Behavior Analysis", "description": "Identify patterns in customer data" } ], "tags": "data,analysis,python,ml,ai", "is_free": false, "price_usd": 19.99, "category": "data-science", "seller_wallet_address": "your-wallet-address" }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/add-agent" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } data = { "name": "Data Analysis Agent", "agent": "from swarms import Agent\n\nclass DataAnalysisAgent(Agent):\n def analyze(self, data):\n # Analysis logic here\n pass", "description": "An AI agent specialized in analyzing large datasets and generating actionable insights", "language": "python", "requirements": [ { "package": "pandas", "installation": "pip install pandas" }, { "package": "numpy", "installation": "pip install numpy" } ], "useCases": [ { "title": "Financial Data Analysis", "description": "Analyze financial statements and market trends" } ], "tags": "data,analysis,python,ml,ai", "is_free": False, "price_usd": 19.99, "category": "data-science", "seller_wallet_address": "your-wallet-address" } response = requests.post(url, json=data, headers=headers) print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/add-agent', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Data Analysis Agent', agent: 'from swarms import Agent\n\nclass DataAnalysisAgent(Agent):\n def analyze(self, data):\n # Analysis logic here\n pass', description: 'An AI agent specialized in analyzing large datasets and generating actionable insights', language: 'python', requirements: [ { package: 'pandas', installation: 'pip install pandas' }, { package: 'numpy', installation: 'pip install numpy' } ], useCases: [ { title: 'Financial Data Analysis', description: 'Analyze financial statements and market trends' } ], tags: 'data,analysis,python,ml,ai', is_free: false, price_usd: 19.99, category: 'data-science', seller_wallet_address: 'your-wallet-address' }) }); const data = await response.json(); console.log(data); ``` </CodeGroup> *** ## Step 3: Update or Query Agents You can easily change agent info or search/filter agents—just as effortlessly as creating one! ### Update Agent #### Endpoint ``` POST /api/edit-agent ``` #### Request Body All fields from the create agent endpoint are available, plus: <ParamField type="string"> The unique ID of the agent you want to update </ParamField> #### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/edit-agent \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Data Analysis Agent", "description": "Updated description with new capabilities", "price_usd": 24.99, "tags": "data,analysis,python,ml,ai,advanced" }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/edit-agent" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } data = { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Data Analysis Agent", "description": "Updated description with new capabilities", "price_usd": 24.99, "tags": "data,analysis,python,ml,ai,advanced" } response = requests.post(url, json=data, headers=headers) print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/edit-agent', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ id: '550e8400-e29b-41d4-a716-446655440000', name: 'Advanced Data Analysis Agent', description: 'Updated description with new capabilities', price_usd: 24.99, tags: 'data,analysis,python,ml,ai,advanced' }) }); const data = await response.json(); console.log(data); ``` </CodeGroup> #### Success Response ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000", "updated_data": { // Updated agent fields } } ``` *** ### Query Agents #### Endpoint ``` POST /api/query-agents ``` #### Request Body <ParamField type="string"> Look up a single agent by its ID </ParamField> <ParamField type="string"> Return the agents owned by this username </ParamField> <ParamField type="string"> Match agent names (substring / slug match) </ParamField> <ParamField type="number"> Number of agents to return (1-100) </ParamField> Only approved agents are returned. #### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/query-agents \ -H "Content-Type: application/json" \ -d '{ "agent_name": "data-analysis", "limit": 10 }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/query-agents" headers = {"Content-Type": "application/json"} data = { "agent_name": "data-analysis", "limit": 10 } response = requests.post(url, json=data, headers=headers) agents = response.json() print(agents) ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/query-agents', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_name: 'data-analysis', limit: 10 }) }); const agents = await response.json(); console.log(agents); ``` </CodeGroup> #### Example Response ```json theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Data Analysis Agent", "description": "An AI agent specialized in data analysis", "language": "python", "requirements": [ { "package": "pandas", "installation": "pip install pandas" } ], "use_cases": [ { "title": "Financial Analysis", "description": "Analyze financial data" } ], "tags": "data,analysis,python", "is_free": false, "price_usd": 19.99, "price": 0.05, "category": "data-science", "status": "approved", "image_url": "https://example.com/image.jpg", "file_path": null, "links": null, "seller_wallet_address": null, "user_id": "user-123", "created_at": "2024-01-15T10:30:00Z", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000" } ], "query_type": "slug", "query_value": "data-analysis", "total": 1 } ``` *** ## Rate Limiting All agent management endpoints are subject to rate limiting: * **Daily Limit**: 3 paid agents per user per day (15 for VIP accounts); 500 free items (agents + prompts) per user per day * **Reset Time**: Midnight If you exceed the limit, you'll receive a `429` error response: ```json theme={null} { "error": "Daily limit exceeded", "message": "Daily limit reached: 3 paid agents per day. Resets at midnight.", "currentUsage": { "paidAgents": 3, "paidPrompts": 0, "freeContent": 0, "date": "2024-01-01" }, "limits": { "paidAgents": 3, "paidPrompts": 500, "freeContent": 500 }, "resetTime": "2024-01-02T00:00:00.000Z" } ``` *** ## Error Responses The API uses standard HTTP status codes to signal errors: * `200`: Success * `400`: Bad Request (validation errors) * `401`: Unauthorized * `403`: Forbidden (paid content without access) * `404`: Not Found * `429`: Too Many Requests * `500`: Internal Server Error ### Example Error Response All endpoints return consistent error responses: ```json theme={null} { "error": "Error message", "message": "Detailed error description", "code": "ERROR_CODE" } ``` Validation errors may include `details`, `errors`, and `status_code`. Duplicate agent responses include `existingId`. Rate limit (429) responses include `currentUsage`, `limits`, and `resetTime`. Authentication (401) responses may include `how_to_get_key`. *** ## Content Validation Every agent undergoes automated checks, including: * **Duplicate Detection**: Same name and same `agent` content for the same user returns 400 with `existingId` * **Quality Assessment**: Checks code completeness and standards * **Security Scanning**: Ensures code is safe * **Trustworthiness Scoring**: Rates each agent on quality and trust (content validation responses may include `trustworthiness`, `contentQuality`) Agents failing validation get a `400 Bad Request` with detailed reasons. *** **In summary: you can create, edit, or search for agents in the Swarms marketplace in just 3 easy steps!** # Agents vs Prompts Source: https://docs.swarms.ai/docs/marketplace/agents-vs-prompts Understanding the differences between Agents and Prompts in the Swarms Marketplace The Swarms Marketplace offers two primary product types: **Agents** and **Prompts**. While both are designed to enhance AI capabilities, they serve different purposes and have distinct features. *** ## Quick Comparison | Feature | Agents | Prompts | | ------------------------- | -------------------------- | --------------------------------------------- | | **Code** | ✅ Contains executable code | ❌ No code | | **Requirements** | ✅ Package dependencies | ❌ None | | **Environment Variables** | ✅ Configurable | ❌ None | | **Export to ChatGPT** | ❌ Not available | ✅ Available | | **Export to Claude** | ❌ Not available | ✅ Available | | **View Modes** | Overview, JSON Metadata | Chat, Preview, Markdown, Text, Framework, API | | **Downloadable Files** | ✅ Code files | ❌ Text only | *** ## Agents Agents are **autonomous AI entities with executable code**. They contain implementation logic that can be run, configured, and integrated into your applications. ### Key Features <CardGroup> <Card title="Executable Code" icon="code"> Agents include actual code (Python, JavaScript, etc.) that implements the agent's logic and behaviors. </Card> <Card title="Package Requirements" icon="box"> Agents specify their dependencies, showing which packages need to be installed (e.g., `pip install swarms`). </Card> <Card title="Environment Variables" icon="key"> Agents can require environment variables for API keys and configuration. </Card> <Card title="Downloadable Files" icon="download"> Download the agent's code files directly from the marketplace. </Card> </CardGroup> ### Agent Page Sections When viewing an agent in the marketplace, you'll see: * **Overview** - Description, use cases, and general information * **JSON Metadata** - Structured data about the agent * **Requirements** - List of packages and installation commands * **Environment Variables** - Required configuration variables * **Agent Code** - The full implementation code with syntax highlighting ### Best For * Complex automation tasks * Multi-step workflows * Integration with external APIs and tools * Custom logic and behaviors * Reusable code components *** ## Prompts Prompts are **system prompt templates without any code**. They define how an AI should behave, respond, and process information through natural language instructions. ### Key Features <CardGroup> <Card title="No Code Required" icon="file-lines"> Prompts are pure text instructions—no programming knowledge needed to use them. </Card> <Card title="Export to ChatGPT" icon="arrow-up-right-from-square"> One-click export to use the prompt directly in ChatGPT. </Card> <Card title="Export to Claude" icon="arrow-up-right-from-square"> One-click export to use the prompt directly in Claude. </Card> <Card title="Multiple View Modes" icon="eye"> View prompts in different formats: Chat, Preview, Markdown, Text, Framework, or API. </Card> </CardGroup> ### Prompt Page Sections When viewing a prompt in the marketplace, you'll see: * **Main Prompt** - The full prompt text with multiple view options: * **Chat** - Interactive chat preview * **Preview** - Formatted preview * **Markdown** - Raw markdown format * **Text** - Plain text format * **Framework** - Format for Swarms Framework integration * **API** - Format for API integration ### Export to AI Platforms Prompts include an **"Export to AI"** feature that allows you to: * Export directly to **ChatGPT** for immediate use * Export directly to **Claude** for immediate use This makes it easy to try prompts across different AI platforms without manual copying. ### Best For * System prompts for AI assistants * Persona definitions * Task-specific instructions * Role-playing scenarios * Structured output templates *** ## When to Use Each ### Choose Agents When: * You need custom logic and automation * Your solution requires specific packages or dependencies * You want to run code locally or in your infrastructure * You're building complex multi-agent workflows * You need integration with external APIs or databases ### Choose Prompts When: * You want to define AI behavior without coding * You need portable instructions that work across platforms * You want to quickly test prompts in ChatGPT or Claude * You're creating persona or role definitions * You want to share prompt engineering techniques *** ## Availability Across Platforms ### Agents Agents are available through: * **Swarms Python Framework** - Import and run directly * **Swarms API** - Access via REST API ### Prompts Prompts are available through: * **Swarms Python Framework** - Use as system prompts * **Swarms API** - Query and retrieve via REST API * **Swarms Chat** - Use directly in the chat interface * **ChatGPT** - Export and use * **Claude** - Export and use *** ## Examples ### Agent Example An agent like "ETF Analysis BatchedGridWorkflow" includes: * Python code for risk analysis and quantitative evaluation * Requirements: `swarms`, `httpx` * Environment variables: `SWARMS_API_KEY` * Downloadable `main.py` file ### Prompt Example A prompt like "Medical Researcher System Prompt" includes: * Detailed instructions for clinical research analysis * Multiple view formats (Chat, Markdown, Text, etc.) * Export options to ChatGPT and Claude * No code or dependencies *** ## Summary <Info> **Agents** = Code + Logic + Dependencies → For developers building automated solutions **Prompts** = Instructions + Templates → For anyone defining AI behavior without code </Info> Both product types can be tokenized on the marketplace and are subject to the same quality validation process. Choose the type that best fits your needs and technical requirements. # Overview Source: https://docs.swarms.ai/docs/marketplace/api-overview Quick reference for all Swarms Marketplace APIs - endpoints, methods, and authentication requirements The Swarms Marketplace provides a comprehensive set of APIs for managing agents, prompts, token launches, and fee claims. This page provides a quick reference to help you find the right endpoint for your needs. ## Base URLs | Service | Base URL | | --------------- | -------------------------- | | Marketplace API | `https://swarms.world` | | Swarms API | `https://api.swarms.world` | *** ## Marketplace API Endpoints at a Glance | API | Endpoint | Method | Auth Required | Description | | ---------------- | ------------------------- | ------ | ------------- | ----------------------------------------------------------------- | | **Products** | `/api/product/list` | GET | Yes | List all products you've posted (agents, prompts, tools, bundles) | | **Products** | `/api/product/fees` | GET | Yes | Check creator fees generated by a tokenized product | | **Agents** | `/api/add-agent` | POST | Yes | Create a new agent listing | | **Agents** | `/api/edit-agent` | POST | Yes | Update an existing agent | | **Agents** | `/api/query-agents` | POST | No | Search and filter agents | | **Prompts** | `/api/add-prompt` | POST | Yes | Create a new prompt | | **Prompts** | `/api/edit-prompt` | POST | Yes | Update an existing prompt | | **Prompts** | `/api/query-prompts` | POST | No | Search and filter prompts | | **Bundles** | `/api/v1/publish/bundle` | POST | Yes | Publish a bundle (curated collection of agents/prompts) | | **Token Launch** | `/api/token/launch` | POST | Yes | Create agent and launch token on Solana | | **Token Launch** | `/api/token/launch/batch` | POST | Yes | Launch up to 50 tokenized agents in one request | | **Reviews** | `/api/reviews` | POST | Yes | Submit a rating and review for an agent, prompt, or tool | | **Claim Fees** | `/api/product/claimfees` | POST | No | Claim accumulated creator fees | *** ## Authentication Most endpoints require authentication via API key in the `Authorization` header as `Bearer YOUR_API_KEY`. Get your API key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). *** ## Marketplace API Categories ### Products API Read your own marketplace catalog and the fees your tokenized products have earned. | Endpoint | Method | Auth | Purpose | | ------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------- | | `/api/product/list` | GET | Required | List all products you've posted (agents, prompts, tools, bundles) with name, description, time posted, and public URL | | `/api/product/fees` | GET | Required | Check creator fees (via Jupiter) generated by a tokenized product, by ticker, UUID, or URL | **Key Features:** * Single call to list every product type you own * Fee amounts reported live in SOL (total, unclaimed, claimed) * Identify products by ticker, UUID, or full Swarms URL <CardGroup> <Card title="List Products API" icon="list" href="/docs/marketplace/list-products-api"> List all products you've posted </Card> <Card title="Product Fees API" icon="coins" href="/docs/marketplace/product-fees-api"> Check creator fees for a tokenized product </Card> </CardGroup> *** ### Agents API Manage AI agents in the marketplace - create, update, and discover agents programmatically. | Endpoint | Method | Auth | Purpose | | ------------------- | ------ | -------- | ---------------------------------------------------------------- | | `/api/add-agent` | POST | Required | Create a new agent with code, description, pricing, and metadata | | `/api/edit-agent` | POST | Required | Update agent details (requires agent `id`) | | `/api/query-agents` | POST | Optional | Search agents by keyword, category, price, and more | **Key Features:** * Support for free and paid agents * Automatic content validation and quality assessment * Blockchain tokenization support * Rate limit: 3 paid agents/day per user (500/day for free agents) <Card title="Full Documentation" icon="book" href="/docs/marketplace/agents-api"> View complete Agents API reference with examples </Card> *** ### Prompts API Manage AI prompts in the marketplace - create reusable prompt templates and discover existing prompts. | Endpoint | Method | Auth | Purpose | | -------------------- | ------ | -------- | ---------------------------------------------------- | | `/api/add-prompt` | POST | Required | Create a new prompt with use cases and metadata | | `/api/edit-prompt` | POST | Required | Update prompt details (requires prompt `id`) | | `/api/query-prompts` | POST | Optional | Search prompts by keyword, category, price, and more | **Key Features:** * Use prompts directly with agents via `marketplace_prompt_id` * Automatic USD to SOL price conversion * Content safety and quality validation * Rate limit: 500 prompts/day per user <Card title="Full Documentation" icon="book" href="/docs/marketplace/prompts-api"> View complete Prompts API reference with examples </Card> *** ### Bundles API Publish [bundles](/docs/marketplace/bundles) — curated collections of marketplace agents, prompts, and custom inline prompts — programmatically. | Endpoint | Method | Auth | Purpose | | ------------------------ | ------ | -------- | ------------------------------------------------------------------------------- | | `/api/v1/publish/bundle` | POST | Required | Publish a bundle with 1–50 items (marketplace references and/or inline prompts) | **Key Features:** * Mix marketplace listings (by URL) with custom inline prompts * Base64 or URL cover images * Duplicate-name protection (safe request retries) * Rate limit: 20 bundles/day per user <Card title="Full Documentation" icon="book" href="/docs/marketplace/bundles-api"> View complete Bundles API reference with examples </Card> *** ### Token Launch API Create a minimal agent listing and launch an associated token on Solana in a single request. | Endpoint | Method | Auth | Purpose | | ------------------- | ------ | -------- | ---------------------------------------------------- | | `/api/token/launch` | POST | Required | Create agent + launch Solana token (\~0.04 SOL cost) | **Key Features:** * Single request for agent creation and tokenization * Supports JSON and multipart/form-data (for image upload) * Multiple private key formats (JSON array, base64, base58) * Returns token address and pool address <Card title="Full Documentation" icon="book" href="/docs/marketplace/token-launch-api"> View complete Token Launch API reference with examples </Card> *** ### Claim Fees API Claim accumulated creator fees for tokenized agents on Solana. | Endpoint | Method | Auth | Purpose | | ------------------------ | ------ | ---- | ---------------------------------------- | | `/api/product/claimfees` | POST | No\* | Claim fees (requires wallet private key) | \*Authentication is done via wallet private key, not API key. **Key Features:** * Claim accumulated SOL fees * Returns transaction signature and amount claimed * Detailed fee breakdown (unclaimed, claimed, total) * Private key used only in memory, never stored <Card title="Full Documentation" icon="book" href="/docs/marketplace/claim-fees-api"> View complete Claim Fees API reference with examples </Card> *** ## HTTP Status Codes | Code | Meaning | | ----- | ----------------------------------------------------- | | `200` | Success | | `400` | Bad Request - validation errors or invalid parameters | | `401` | Unauthorized - missing or invalid API key | | `403` | Forbidden - paid content without access | | `404` | Not Found | | `405` | Method Not Allowed | | `429` | Too Many Requests - rate limit exceeded | | `500` | Internal Server Error | *** ## Rate Limits | Resource | Limit | Reset | | ------------ | ------------------------------- | -------- | | Paid Agents | 3/day (15/day for VIP accounts) | Midnight | | Paid Prompts | 500/day | Midnight | | Free Content | 500/day | Midnight | When rate limited, you'll receive a `429` response with details about current usage, limits, and reset time. *** ## Related Resources <CardGroup> <Card title="List Products API" icon="list" href="/docs/marketplace/list-products-api"> List all products you've posted </Card> <Card title="Product Fees API" icon="coins" href="/docs/marketplace/product-fees-api"> Check creator fees for a tokenized product </Card> <Card title="Agents API" icon="robot" href="/docs/marketplace/agents-api"> Complete reference for agent management </Card> <Card title="Prompts API" icon="file-lines" href="/docs/marketplace/prompts-api"> Complete reference for prompt management </Card> <Card title="Token Launch API" icon="rocket" href="/docs/marketplace/token-launch-api"> Launch tokenized agents on Solana </Card> <Card title="Claim Fees API" icon="coins" href="/docs/marketplace/claim-fees-api"> Claim your creator fees </Card> <Card title="Examples" icon="code" href="/docs/marketplace/examples"> Real-world integration examples </Card> <Card title="Creator Fees" icon="percent" href="/docs/marketplace/creator-fees"> Understand the fee structure </Card> </CardGroup> # API Keys Source: https://docs.swarms.ai/docs/marketplace/apikeys Create, manage, and secure API keys for programmatic access to your Swarms account. This document provides detailed information on managing API keys within the Swarms Platform. API keys grant programmatic access to your account and should be handled securely. Follow the guidelines below to manage your API keys safely and effectively. *** ## Table of Contents 1. [Overview](#overview) 2. [Viewing Your API Keys](#viewing-your-api-keys) 3. [Creating a New API Key](#creating-a-new-api-key) 4. [Security Guidelines](#security-guidelines) 5. [Frequently Asked Questions](#frequently-asked-questions) *** ## Overview API keys are unique credentials that allow you to interact with the Swarms Platform programmatically. These keys enable you to make authenticated API requests to access or modify your data. **Important:** Once a secret API key is generated, it will not be displayed again. Ensure you store it securely, as it cannot be retrieved from the platform later. *** ## Viewing Your API Keys When you navigate to the API Keys page ([https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys)), you will see a list of your API keys along with the following information: ### Key Details: * **Name:** A label you assign to your API key to help you identify it. * **Key:** The secret API key is only partially visible here for security reasons. * **Created Date:** The date when the API key was generated. * **Actions:** Options available for managing the key (e.g., deleting an API key). *** ## Creating a New API Key To generate a new API key, follow these steps: 1. **Attach a Credit Card (only if you have no credits):**\ A card is required only when your account has no remaining credit balance. Accounts that still hold free, purchased, or referral credits can create a key without one. 2. **Access the API Keys Page:**\ Navigate to [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). 3. **Generate a New Key:**\ Click on the **"Create new API key"** button. The system will generate a new secret API key for your account. 4. **Store Your API Key Securely:**\ Once generated, the full API key will be displayed only once. Copy and store it in a secure location, as it will not be displayed again.\ **Note:** Do not share your API key with anyone or expose it in any client-side code (e.g., browser JavaScript). *** ## Security Guidelines * **Confidentiality:**\ Your API keys are sensitive credentials. Do not share them with anyone or include them in public repositories or client-side code. * **Storage:**\ Store your API keys in secure, encrypted storage. Avoid saving them in plain text files or unsecured locations. * **Rotation:**\ If you suspect that your API key has been compromised, immediately delete it and create a new one. * **Access Control:**\ Limit access to your API keys to only those systems and personnel who absolutely require it. *** ## Frequently Asked Questions ### Q1: **Why do I need a credit card attached to my account to create an API key?** **A:** A card is only requested once your credit balance reaches zero. It helps verify your identity and manage billing, ensuring responsible usage of the API services provided by the Swarms Platform. ### Q2: **What happens if I lose my API key?** **A:** If you lose your API key, you will need to generate a new one. The platform does not store the full key after its initial generation, so recovery is not possible. ### Q3: **How can I delete an API key?** **A:** On the API Keys page, locate the key you wish to delete and click the **"Delete"** action next to it. This will revoke the key's access immediately. ### Q4: **Can I have multiple API keys?** **A:** Yes, you can generate and manage multiple API keys. Use naming conventions to keep track of their usage and purpose. *** For any further questions or issues regarding API key management, please refer to our [Support page](https://swarms.world/support) or contact our support team. # Bundles Source: https://docs.swarms.ai/docs/marketplace/bundles Package agents and prompts into a single, shareable, reusable toolkit on the Swarms Marketplace A **Bundle** is a curated collection of agents and prompts, packaged together into one shareable toolkit. Instead of sharing a dozen scattered links, you assemble your best agents and prompts—plus your own custom prompts—into a single product that anyone can access, bookmark, and reuse with one click. Bundles are a first-class marketplace product type, sitting alongside [Agents and Prompts](/docs/marketplace/agents-vs-prompts). They add a layer of human curation on top of the marketplace: pre-assembled solution kits for a specific use case. *** ## What Is a Bundle? Bundles are **meta-products**—they aggregate other items into a themed collection. A single bundle can combine: <CardGroup> <Card title="Marketplace Agents" icon="robot"> Reference any existing agent by its marketplace URL. The bundle automatically enriches it with the agent's real name and description. </Card> <Card title="Marketplace Prompts" icon="message-lines"> Reference any existing prompt from the marketplace the same way, pulling in its live details. </Card> <Card title="Custom Prompts" icon="pen-to-square"> Write your own inline prompts—name, description, and prompt content—without publishing them as standalone listings. </Card> <Card title="Related Links" icon="link"> Add optional supporting links such as docs, GitHub repos, or demos in a dedicated sidebar. </Card> </CardGroup> <Note> Every bundle requires at least one item. Bundles are **free to create** and free for others to access. </Note> *** ## How to Launch a Bundle Launching a Bundle takes less than a minute. <Note> Prefer code over clicks? Bundles can also be published programmatically via the [Bundles API](/docs/marketplace/bundles-api) (`POST /api/v1/publish/bundle`). </Note> <Steps> <Step title="Sign Up"> Create an account or sign in at [swarms.world/signin](https://swarms.world/signin). </Step> <Step title="Go to Publish"> Navigate to [swarms.world/publish](https://swarms.world/publish). </Step> <Step title="Select Bundle"> Choose **"Bundle"** as your product type. </Step> <Step title="Add Bundle Details"> Give your bundle a name (min. 2 characters) and a description (min. 10 characters). Add comma-separated tags—or let the platform auto-generate them—and upload a cover image (images, GIFs, and video files are supported). </Step> <Step title="Add Your Items"> Build the toolkit by adding items in either of two ways: * **Marketplace URL** — paste a link to an existing agent or prompt * **Custom Prompt** — write a prompt inline with its own name, description, and content Add as many as you like. Optionally include **Related Links** (docs, GitHub, etc.). </Step> <Step title="Publish"> Hit **Publish**. Your bundle gets its own public page, and you're redirected to it. </Step> </Steps> That's it. Your entire toolkit is now packaged into one reusable, discoverable Bundle. *** ## Sharing and Growing Your Bundle Every bundle is built to spread. Once published, it grows through marketplace-native discovery. <CardGroup> <Card title="One-Click Share Link" icon="share-nodes"> Each bundle has its own public page at `swarms.world/bundle/{id}` and a **Share Link** button that copies the URL to your clipboard. Drop it anywhere. </Card> <Card title="Marketplace Discovery" icon="store"> Bundles appear in the dedicated **Bundles** section of the marketplace and can be filtered as their own category. </Card> <Card title="Creator Profile" icon="user"> Every bundle you publish is listed under the **Bundles** tab on your creator profile, building your portfolio. </Card> <Card title="Bookmarks" icon="bookmark"> Other users can bookmark your bundle to their personal collection for quick access later. </Card> <Card title="Ratings & Reviews" icon="star"> Bundles collect ratings and reviews, giving them built-in social proof and credibility. </Card> <Card title="Comments & Discussion" icon="comments"> Each bundle page has a discussion section where users can ask questions and leave feedback. </Card> </CardGroup> <Tip> Bundles include full SEO support—Open Graph tags, Twitter cards, and schema.org structured data—so shared links render rich previews on social platforms and rank in search. </Tip> *** ## Why Use Bundles? Bundles keep everything in one place. Instead of sharing a dozen scattered links, you package agents and prompts into a single, reusable toolkit that anyone can access with one click. * **One link, not ten** — distribute an entire workflow as a single product. * **Context stays together** — agents and prompts that were meant to work as a set ship as a set. * **Built-in credibility** — ratings, reviews, and bookmarks travel with the bundle. * **Build once, share everywhere** — a reusable asset you assemble a single time. * **Free to create** — no cost to publish or to access. *** ## When to Use Bundles Reach for a bundle whenever you want to package and distribute expertise: | Use Case | Example | | ------------------------------ | ------------------------------------------------------------------------- | | **Research stacks** | A collection of research, summarization, and citation agents and prompts. | | **Trading toolkits** | Market-analysis agents paired with strategy prompts. | | **Customer support workflows** | Triage, response, and escalation prompts in one kit. | | **Team onboarding kits** | A vetted set of tools to get new teammates productive fast. | | **Educational courses** | Package the tools behind a tutorial or course in one place. | | **Showcase collections** | Curate and highlight your best work on your profile. | *** ## Bundles vs. Agents and Prompts | Feature | Bundles | Agents | Prompts | | --------------------- | --------------------------------- | ------------------- | ---------------------- | | **Contains** | Agents + prompts + custom prompts | Executable code | System prompt template | | **Purpose** | Curated toolkit / collection | Autonomous AI logic | Behavior instructions | | **Pricing** | Free only | Free or paid | Free or paid | | **Shareable page** | ✅ | ✅ | ✅ | | **Ratings & reviews** | ✅ | ✅ | ✅ | | **Bookmarks** | ✅ | ✅ | ✅ | <Note> Bundles are currently **free-only**. The underlying platform has groundwork for future monetization, but pricing controls are not yet enabled for bundles. </Note> *** ## Next Steps <CardGroup> <Card title="Launch a Bundle" icon="rocket" href="https://swarms.world/publish"> Head to the publish page and select "Bundle" to get started. </Card> <Card title="Bundles API" icon="code" href="/docs/marketplace/bundles-api"> Publish bundles programmatically with your API key. </Card> <Card title="Agents vs Prompts" icon="scale-balanced" href="/docs/marketplace/agents-vs-prompts"> Understand the building blocks you'll add to your bundles. </Card> <Card title="Share & Discover" icon="compass" href="/docs/marketplace/share_and_discover"> Learn more about discovery and sharing across the marketplace. </Card> <Card title="Monetize Your Work" icon="dollar-sign" href="/docs/marketplace/monetize"> Explore how creators earn on the Swarms Marketplace. </Card> </CardGroup> # Bundles API Source: https://docs.swarms.ai/docs/marketplace/bundles-api Publish bundles to the Swarms marketplace programmatically Publish a [Bundle](/docs/marketplace/bundles) — a curated collection of marketplace agents, prompts, and custom inline prompts — straight from your code or CI pipeline, in **3 easy steps**: 1. **Authenticate**: Secure your request with an API key. 2. **Publish**: POST your bundle's name, description, and items. 3. **Get your listing**: Instantly receive the public bundle URL. *** ## Step 1: Authentication Send your API key in the `Authorization` header as a Bearer token: ``` Authorization: Bearer <your-api-key> ``` <Note> Get your API key from [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). </Note> ## Base URL ``` https://swarms.world ``` *** ## Step 2: Publish a Bundle ### Endpoint ``` POST /api/v1/publish/bundle ``` ### Input schema | Parameter | Type | Required | Description | | ---------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------ | | `name` | string | Yes | Bundle display name (2–200 characters). Names containing `test` or `example` are rejected. | | `description` | string | No | What the bundle is for (max 10,000 characters) | | `items` | array | Yes | 1–50 bundle items — see item shape below | | `tags` | string | No | Comma-separated tags (max 500 characters) | | `image_url` | string | No | Public cover image URL | | `image_base64` | string | No | Base64-encoded cover image (alternative to `image_url`; may include a `data:image/...;base64,` prefix) | | `links` | array | No | Supporting links; each `{ "name": string, "url": string }` (max 20) | | `business_model` | string | No | Optional business model label | ### Item shape Each entry in `items` is **one of two kinds**: | Kind | Fields | Description | | --------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Marketplace reference | `url` | Link to an existing agent or prompt listing, e.g. `https://swarms.world/agent/<id>`. The bundle page enriches it with the live name and description. | | Custom inline prompt | `name` (required), `description`, `content` | A prompt bundled directly without publishing it as a standalone listing | <Note> Every item needs either a `url` or a `name`. A bundle must contain at least one item. Bundles are free products — free to publish and free to access. </Note> ### Example request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/v1/publish/bundle \ -H "Authorization: Bearer $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Financial Analysis Starter Kit", "description": "Everything you need to analyze equities: a research agent, a summarizer prompt, and my custom risk checklist.", "tags": "finance,research,analysis", "items": [ { "url": "https://swarms.world/agent/2d5bd840-2830-4b2f-9709-02cab69a442b" }, { "url": "https://swarms.world/prompt/e0686b13-7f41-44f4-adc4-6c1f468793fb" }, { "name": "Risk Checklist", "description": "Pre-trade risk review", "content": "Before recommending any position, verify: 1) liquidity..." } ], "links": [ { "name": "GitHub", "url": "https://github.com/your-org/finance-kit" } ] }' ``` ```python Python theme={null} import os import requests response = requests.post( "https://swarms.world/api/v1/publish/bundle", headers={ "Authorization": f"Bearer {os.environ['SWARMS_API_KEY']}", "Content-Type": "application/json", }, json={ "name": "Financial Analysis Starter Kit", "description": "Everything you need to analyze equities.", "tags": "finance,research,analysis", "items": [ {"url": "https://swarms.world/agent/2d5bd840-2830-4b2f-9709-02cab69a442b"}, { "name": "Risk Checklist", "description": "Pre-trade risk review", "content": "Before recommending any position, verify: ...", }, ], }, timeout=30, ) print(response.json()) ``` ```typescript TypeScript theme={null} const response = await fetch("https://swarms.world/api/v1/publish/bundle", { method: "POST", headers: { Authorization: `Bearer ${process.env.SWARMS_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Financial Analysis Starter Kit", description: "Everything you need to analyze equities.", tags: "finance,research,analysis", items: [ { url: "https://swarms.world/agent/2d5bd840-2830-4b2f-9709-02cab69a442b" }, { name: "Risk Checklist", description: "Pre-trade risk review", content: "Before recommending any position, verify: ...", }, ], }), }); console.log(await response.json()); ``` </CodeGroup> *** ## Step 3: Get Your Listing ### Success response ```json theme={null} { "success": true, "id": "b3f1c2d4-5678-4abc-9def-0123456789ab", "listing_url": "https://swarms.world/bundle/b3f1c2d4-5678-4abc-9def-0123456789ab", "item_count": 3 } ``` | Field | Type | Description | | ------------- | ------- | ------------------------------------- | | `success` | boolean | `true` when the bundle was published | | `id` | string | The bundle's public identifier (UUID) | | `listing_url` | string | Public marketplace URL of your bundle | | `item_count` | number | Number of items saved in the bundle | ### Error responses | Status | Error | Meaning | | ------ | -------------------------------------- | ------------------------------------------------------------------------------------------------- | | `400` | Validation error | Request body failed schema validation — see the `errors` array for details | | `400` | Invalid name | Name contains a blocked word (`test`, `example`) | | `401` | Authentication required | Missing or invalid API key | | `405` | Method not allowed | Only `POST` is accepted | | `409` | Duplicate bundle | You already have a bundle with this name — the response includes `existing_id` and `existing_url` | | `429` | Daily limit exceeded | Maximum 20 bundles per user per day | | `500` | Database error / Internal server error | Something went wrong on our side — retry later | <Note> **Rate limit:** 20 bundles per user per UTC day. Duplicate names (same user, same bundle name) are rejected with `409` so retried requests never double-publish. </Note> *** ## Related <CardGroup> <Card title="Bundles Overview" icon="box" href="/docs/marketplace/bundles"> What bundles are and how they work on the marketplace </Card> <Card title="List Your Products" icon="list" href="/docs/marketplace/list-products-api"> Fetch everything you've published, including bundles </Card> <Card title="Agents API" icon="robot" href="/docs/marketplace/agents-api"> Publish agents programmatically </Card> <Card title="API Keys" icon="key" href="/docs/marketplace/apikeys"> Create and manage your API keys </Card> </CardGroup> # Marketplace Business Models Source: https://docs.swarms.ai/docs/marketplace/business-models Every way to monetize on the Swarms Marketplace: crypto paid, fiat paid, tokenization, frenzy tokens, and vault mode, compared side by side. The Swarms Marketplace supports multiple business models for publishing agents and prompts. Every listing picks its model at launch time on [swarms.world/launch](https://swarms.world/launch), from simple one-time purchases in fiat or crypto, to fully tokenized products with tradeable tokens, boosted fees, and holder-gated access. ## Comparison table | | **Free** | **Crypto Paid** | **Fiat Paid** | **Tokenization** | **Frenzy Tokens** | **Vault Mode** | | ------------------------- | ------------------------ | --------------------------------- | --------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------- | -------------------------------------------- | | **What it is** | Open access for everyone | One-time purchase paid in SOL | One-time purchase paid by card via Stripe | Product gets its own tradeable token on a bonding curve | Tokenization upgrade with 2× trading fees | Token-gated access: holders only | | **Buyer pays with** | Nothing | SOL (Phantom wallet) | Cards, Apple Pay, Google Pay, Alipay, crypto & more | SOL or USDC (buys the token) | SOL or USDC (buys the token) | Any amount of the product's token | | **How the creator earns** | None | 90% of each sale in SOL | 90% of each sale, paid out to bank | Bonding curve trading fees on every buy/sell | **Double** bonding curve fees on every trade | Token demand + trading fees | | **Platform fee** | None | 10% per sale | 10% per sale | Volume-based trading fees | Volume-based trading fees (2×) | Volume-based trading fees | | **Launch cost** | Free | Free | Free | 0.04 SOL mint fee | 0.04 SOL mint fee | 0.04 SOL mint fee | | **Creator needs** | Nothing | Solana wallet | Stripe seller account | Solana wallet | Solana wallet | Solana wallet | | **Buyer needs** | Nothing | Phantom wallet | Nothing, normal checkout | Solana wallet | Solana wallet | Solana wallet holding the token | | **Access model** | Everyone | Lifetime after purchase | Lifetime after purchase | Open listing, tradeable token | Open listing, tradeable token | Holders only, unlocked while holding | | **Payouts** | None | Instant SOL to your wallet | Automatic bank payouts via Stripe | Claimable creator fees | Claimable creator fees (2×) | Claimable creator fees | | **Extra perks** | Reach & reputation | None | 100+ countries, multi-currency | Price discovery, community ownership | Frenzy leaderboard + FRENZY badge | Built-in Buy \$TICKER widget, creator bypass | | **Configured via** | Launch page | Launch page → Paid → Crypto (SOL) | Launch page → Paid → Card / Fiat | Launch page → Tokenization | Tokenization → Frenzy (`fee_selection: "frenzy"`) | Tokenization → Vault Mode | ## Choosing a model ```mermaid theme={null} graph TD A["How do you want to monetize?"] --> B["Simple one-time price"] A --> C["Tradeable token"] A --> D["Just build reach"] D --> FREE["FREE<br/>open access, no fees"] B --> B1{"How should buyers pay?"} B1 -- "Cards, Apple Pay, Alipay..." --> FIAT["FIAT PAID<br/>Stripe checkout, bank payouts<br/>10% fee"] B1 -- "SOL from a wallet" --> CRYPTO["CRYPTO PAID<br/>Phantom checkout, SOL payouts<br/>10% fee"] C --> TOK["TOKENIZATION<br/>bonding curve token, 0.04 SOL mint<br/>trading fees accrue to you"] TOK --> T1{"Want more?"} T1 -- "2x fees + leaderboard" --> FRENZY["FRENZY TOKENS"] T1 -- "Holders-only access" --> VAULT["VAULT MODE"] ``` ## The models in depth ### Free Open access for every visitor. No fees for creators or users. The fastest way to build reputation, reviews, and reach on the marketplace, and the required pricing for Vault Mode listings, since the token itself is the gate. ### Crypto Paid (SOL) A fixed USD price paid in SOL. Buyers connect a Phantom wallet and pay in one transaction; the seller's share (90%) lands directly in their Solana wallet and the platform retains a 10% commission. Requires a Solana wallet address on the listing. ### Fiat Paid (Stripe) The same fixed-price model, powered by Stripe. Buyers in **100+ countries** check out with cards, **Apple Pay, Google Pay, Alipay, crypto**, and more, in 100+ currencies, with no wallet required. Sellers onboard once via the [Seller tab](https://swarms.world/platform/account?tab=seller) and receive automatic bank payouts of 90% per sale; the platform fee is the same 10% as crypto. See the [Fiat Payments Overview](/docs/marketplace/fiat-payments). ### Tokenization Instead of a fixed price, the product launches its own token on a bonding curve (SOL- or USDC-denominated) for a one-time 0.04 SOL mint fee. Anyone can trade the token; the creator earns trading fees on every buy and sell, claimable from the [Creator Fees](/docs/marketplace/creator-fees) dashboard. Tokenization can also be **combined with paid pricing**: the product carries a token *and* a USD access price. See [Tokenization](/docs/marketplace/tokenization_details). ### Frenzy Tokens A tokenization upgrade: the token launches on a 2× fee configuration, doubling the bonding curve fees collected on every trade, and earns a spot on the high-visibility **Frenzy leaderboard** with an animated FRENZY badge. Launch cost is unchanged (0.04 SOL). See [Frenzy Mode](/docs/marketplace/frenzy-mode). ### Vault Mode Token-gated distribution: the full listing (system prompt, code, metadata) is blurred for anyone who doesn't hold the product's token, with a built-in **Buy \$TICKER** widget to unlock it. Any non-zero balance unlocks the page; the creator always has access. Requires tokenization, and pricing stays Free; the token *is* the price. See [Vault Mode](/docs/marketplace/vault-mode). ## Combining models Some models stack; others are exclusive: | Combination | Supported? | Notes | | ------------------------------- | ---------- | ------------------------------------------------------------------- | | Paid + choice of Crypto or Fiat | ✅ | Every paid listing picks exactly one payment rail | | Paid + Tokenization | ✅ | USD access price *and* a tradeable token | | Tokenization + Frenzy | ✅ | Frenzy is a launch-time fee upgrade | | Tokenization + Vault Mode | ✅ | Vault requires a token to gate with | | Frenzy + Vault Mode | ✅ | Who can access (Vault) × how much trades earn (Frenzy) | | Paid + Vault Mode | ❌ | Vault already gates access via holdings; pricing must be Free | | Fiat + Tokenization | ❌ | Tokenized payouts are on-chain; paid+tokenized uses the crypto rail | ## Next steps * [Fiat Payments Overview](/docs/marketplace/fiat-payments): the newest way to sell * [Vendor Tutorial](/docs/marketplace/fiat-payments-vendor-tutorial): set up card payments * [Tokenization Details](/docs/marketplace/tokenization_details): launch a token * [Revenue & Fees](/docs/marketplace/revenue-fees): the full fee structure * [Launch Checklist](/docs/marketplace/launch-checklist): publish with confidence # Claim Fees API Source: https://docs.swarms.ai/docs/marketplace/claim-fees-api Claim accumulated fees for a token on Solana **POST** `https://swarms.world/api/product/claimfees` Claims accumulated fees for a token on Solana. You provide the token mint (contract address) and your wallet's private key; the endpoint builds the claim transaction, signs it with your key, submits it on-chain, and returns the transaction signature **and how much SOL was claimed**. The private key is used only in memory to sign the transaction and is never stored or logged. *** ## Request ### Headers | Name | Type | Required | Description | | -------------- | ------ | -------- | --------------------------- | | `Content-Type` | string | Yes | Must be `application/json`. | ### Body Parameters (JSON) | Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------------------------------------------------------------------------------------- | | `ca` | string | Yes | Token mint / contract address of the coin (Solana address). Must be 32–44 characters. | | `privateKey` | string | Yes | Base58-encoded wallet private key. Used only to sign the claim transaction; must be the fee-owner wallet. | *** ## Response ### Success (HTTP 200) | Field | Type | Description | | ------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------ | | `success` | boolean | Always `true` on success. | | `signature` | string \| null | Solana transaction signature from the claim. May be `null` if the upstream response did not include a signature. | | `amountClaimedSol` | number \| null | SOL amount that was claimed in this request (pre-claim unclaimed amount). `null` if fee info could not be fetched. | | `fees` | object \| null | Fee breakdown (same as entity Creator Fees). `null` if fee info could not be fetched. | | `fees.unclaimedSol` | number | Unclaimed SOL before this claim (same as `amountClaimedSol` on success). | | `fees.claimedSol` | number | Total SOL already claimed (historical). | | `fees.totalSol` | number | Total fees earned (unclaimed + claimed). | **Example success response:** ```json theme={null} { "success": true, "signature": "5V7x...signature...", "amountClaimedSol": 0.42, "fees": { "unclaimedSol": 0.42, "claimedSol": 1.08, "totalSol": 1.5 } } ``` If fee info could not be fetched, `amountClaimedSol` and `fees` will be `null`; `signature` is still returned on success. ### HTTP Status Codes | Code | Meaning | | ----- | ---------------------------------------------------------------------------------------------------- | | `200` | Success; fees claimed and transaction submitted. | | `400` | Bad request: missing `ca` or `privateKey`, invalid token mint format, or invalid base58 private key. | | `405` | Method not allowed; only POST is accepted. | | `500` | Internal server error, or claim transaction failed. | *** ## Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/product/claimfees \ -H "Content-Type: application/json" \ -d '{ "ca": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "privateKey": "YOUR_BASE58_PRIVATE_KEY" }' ``` ```python Python theme={null} import requests BASE_URL = "https://swarms.world" payload = { "ca": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "privateKey": "YOUR_BASE58_PRIVATE_KEY", } response = requests.post( f"{BASE_URL}/api/product/claimfees", headers={"Content-Type": "application/json"}, json=payload, ) data = response.json() if response.ok: print("Signature:", data.get("signature")) if data.get("amountClaimedSol") is not None: print("Amount claimed (SOL):", data["amountClaimedSol"]) if data.get("fees"): print("Fee breakdown:") print(" Unclaimed:", data["fees"]["unclaimedSol"], "SOL") print(" Claimed:", data["fees"]["claimedSol"], "SOL") print(" Total:", data["fees"]["totalSol"], "SOL") else: print("Error:", data.get("error", response.text)) ``` ```typescript TypeScript theme={null} interface ClaimFeesResponse { success: boolean; signature: string | null; amountClaimedSol: number | null; fees: { unclaimedSol: number; claimedSol: number; totalSol: number; } | null; } interface ClaimFeesError { error: string; } async function claimFees( ca: string, privateKey: string ): Promise<ClaimFeesResponse> { const response = await fetch("https://swarms.world/api/product/claimfees", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ca, privateKey }), }); const data = await response.json(); if (!response.ok) { throw new Error((data as ClaimFeesError).error || "Unknown error"); } return data as ClaimFeesResponse; } // Usage async function main() { try { const result = await claimFees( "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY" ); console.log("Signature:", result.signature); if (result.amountClaimedSol !== null) { console.log("Amount claimed (SOL):", result.amountClaimedSol); } if (result.fees) { console.log("Fee breakdown:"); console.log(" Unclaimed:", result.fees.unclaimedSol, "SOL"); console.log(" Claimed:", result.fees.claimedSol, "SOL"); console.log(" Total:", result.fees.totalSol, "SOL"); } } catch (error) { console.error("Error:", error); } } main(); ``` ```go Go theme={null} package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" ) const baseURL = "https://swarms.world" type ClaimFeesRequest struct { CA string `json:"ca"` PrivateKey string `json:"privateKey"` } type Fees struct { UnclaimedSol float64 `json:"unclaimedSol"` ClaimedSol float64 `json:"claimedSol"` TotalSol float64 `json:"totalSol"` } type ClaimFeesResponse struct { Success bool `json:"success"` Signature *string `json:"signature"` AmountClaimedSol *float64 `json:"amountClaimedSol"` Fees *Fees `json:"fees"` } type ErrorResponse struct { Error string `json:"error"` } func claimFees(ca, privateKey string) (*ClaimFeesResponse, error) { payload := ClaimFeesRequest{ CA: ca, PrivateKey: privateKey, } body, err := json.Marshal(payload) if err != nil { return nil, fmt.Errorf("failed to marshal payload: %w", err) } req, err := http.NewRequest("POST", baseURL+"/api/product/claimfees", bytes.NewBuffer(body)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) } if resp.StatusCode != http.StatusOK { var errResp ErrorResponse if err := json.Unmarshal(respBody, &errResp); err != nil { return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(respBody)) } return nil, fmt.Errorf("request failed: %s", errResp.Error) } var result ClaimFeesResponse if err := json.Unmarshal(respBody, &result); err != nil { return nil, fmt.Errorf("failed to unmarshal response: %w", err) } return &result, nil } func main() { result, err := claimFees( "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY", ) if err != nil { fmt.Println("Error:", err) return } if result.Signature != nil { fmt.Println("Signature:", *result.Signature) } if result.AmountClaimedSol != nil { fmt.Printf("Amount claimed (SOL): %.4f\n", *result.AmountClaimedSol) } if result.Fees != nil { fmt.Println("Fee breakdown:") fmt.Printf(" Unclaimed: %.4f SOL\n", result.Fees.UnclaimedSol) fmt.Printf(" Claimed: %.4f SOL\n", result.Fees.ClaimedSol) fmt.Printf(" Total: %.4f SOL\n", result.Fees.TotalSol) } } ``` ```rust Rust theme={null} use reqwest::blocking::Client; use serde::{Deserialize, Serialize}; const BASE_URL: &str = "https://swarms.world"; #[derive(Serialize)] struct ClaimFeesRequest { ca: String, #[serde(rename = "privateKey")] private_key: String, } #[derive(Deserialize, Debug)] struct Fees { #[serde(rename = "unclaimedSol")] unclaimed_sol: f64, #[serde(rename = "claimedSol")] claimed_sol: f64, #[serde(rename = "totalSol")] total_sol: f64, } #[derive(Deserialize, Debug)] struct ClaimFeesResponse { success: bool, signature: Option<String>, #[serde(rename = "amountClaimedSol")] amount_claimed_sol: Option<f64>, fees: Option<Fees>, } #[derive(Deserialize, Debug)] struct ErrorResponse { error: String, } fn claim_fees(ca: &str, private_key: &str) -> Result<ClaimFeesResponse, Box<dyn std::error::Error>> { let client = Client::new(); let payload = ClaimFeesRequest { ca: ca.to_string(), private_key: private_key.to_string(), }; let response = client .post(format!("{}/api/product/claimfees", BASE_URL)) .header("Content-Type", "application/json") .json(&payload) .send()?; if !response.status().is_success() { let error_response: ErrorResponse = response.json()?; return Err(error_response.error.into()); } let result: ClaimFeesResponse = response.json()?; Ok(result) } fn main() -> Result<(), Box<dyn std::error::Error>> { let result = claim_fees( "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY", )?; if let Some(signature) = &result.signature { println!("Signature: {}", signature); } if let Some(amount) = result.amount_claimed_sol { println!("Amount claimed (SOL): {:.4}", amount); } if let Some(fees) = &result.fees { println!("Fee breakdown:"); println!(" Unclaimed: {:.4} SOL", fees.unclaimed_sol); println!(" Claimed: {:.4} SOL", fees.claimed_sol); println!(" Total: {:.4} SOL", fees.total_sol); } Ok(()) } ``` </CodeGroup> *** ## Error Responses ### Error response body (4xx / 5xx) | Field | Type | Description | | ------- | ------ | ------------------------------------------- | | `error` | string | Short error message describing the failure. | ### Example error responses **Missing parameters (400):** ```json theme={null} { "error": "ca (token mint) and privateKey are required in request body" } ``` **Invalid token mint (400):** ```json theme={null} { "error": "Invalid ca (token mint) format" } ``` **Invalid private key (400):** ```json theme={null} { "error": "Invalid privateKey: could not decode base58 secret key" } ``` **Claim / submit failed (500):** Returned when the claim transaction fails (e.g. no fees to claim, network error). ```json theme={null} { "error": "Claim transaction failed" } ``` *** ## Advanced Examples These examples include additional features like retry logic, async support, context/timeout handling, and custom error types. <CodeGroup> ```typescript TypeScript (Retry Logic) theme={null} import { setTimeout } from "timers/promises"; interface ClaimFeesResponse { success: boolean; signature: string | null; amountClaimedSol: number | null; fees: { unclaimedSol: number; claimedSol: number; totalSol: number; } | null; } class ClaimFeesClient { private baseUrl = "https://swarms.world"; private maxRetries: number; private retryDelayMs: number; constructor(options?: { maxRetries?: number; retryDelayMs?: number }) { this.maxRetries = options?.maxRetries ?? 3; this.retryDelayMs = options?.retryDelayMs ?? 1000; } async claimFees( ca: string, privateKey: string ): Promise<ClaimFeesResponse> { let lastError: Error | null = null; for (let attempt = 1; attempt <= this.maxRetries; attempt++) { try { const response = await fetch( `${this.baseUrl}/api/product/claimfees`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ca, privateKey }), } ); const data = await response.json(); if (!response.ok) { // Don't retry client errors (4xx) if (response.status >= 400 && response.status < 500) { throw new Error(data.error || `Client error: ${response.status}`); } throw new Error(data.error || `Server error: ${response.status}`); } return data as ClaimFeesResponse; } catch (error) { lastError = error as Error; console.warn(`Attempt ${attempt} failed:`, lastError.message); if (attempt < this.maxRetries) { const delay = this.retryDelayMs * Math.pow(2, attempt - 1); console.log(`Retrying in ${delay}ms...`); await setTimeout(delay); } } } throw lastError ?? new Error("Failed to claim fees"); } } // Usage async function main() { const client = new ClaimFeesClient({ maxRetries: 3, retryDelayMs: 1000 }); try { const result = await client.claimFees( "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY" ); console.log("Claim successful!"); console.log("Transaction signature:", result.signature); if (result.amountClaimedSol !== null) { console.log(`Claimed ${result.amountClaimedSol} SOL`); } } catch (error) { console.error("Failed to claim fees:", error); process.exit(1); } } main(); ``` ```python Python (Async) theme={null} import asyncio import aiohttp from typing import Optional from dataclasses import dataclass @dataclass class Fees: unclaimed_sol: float claimed_sol: float total_sol: float @dataclass class ClaimFeesResult: success: bool signature: Optional[str] amount_claimed_sol: Optional[float] fees: Optional[Fees] class ClaimFeesClient: def __init__(self, base_url: str = "https://swarms.world"): self.base_url = base_url async def claim_fees( self, ca: str, private_key: str, session: Optional[aiohttp.ClientSession] = None ) -> ClaimFeesResult: close_session = session is None if session is None: session = aiohttp.ClientSession() try: async with session.post( f"{self.base_url}/api/product/claimfees", json={"ca": ca, "privateKey": private_key}, headers={"Content-Type": "application/json"}, ) as response: data = await response.json() if not response.ok: raise Exception(data.get("error", f"Request failed: {response.status}")) fees = None if data.get("fees"): fees = Fees( unclaimed_sol=data["fees"]["unclaimedSol"], claimed_sol=data["fees"]["claimedSol"], total_sol=data["fees"]["totalSol"], ) return ClaimFeesResult( success=data["success"], signature=data.get("signature"), amount_claimed_sol=data.get("amountClaimedSol"), fees=fees, ) finally: if close_session: await session.close() async def main(): client = ClaimFeesClient() try: result = await client.claim_fees( ca="7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", private_key="YOUR_BASE58_PRIVATE_KEY", ) print(f"Claim successful!") print(f"Transaction signature: {result.signature}") if result.amount_claimed_sol is not None: print(f"Claimed {result.amount_claimed_sol} SOL") if result.fees: print(f"Fee breakdown:") print(f" Unclaimed: {result.fees.unclaimed_sol} SOL") print(f" Claimed: {result.fees.claimed_sol} SOL") print(f" Total: {result.fees.total_sol} SOL") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": asyncio.run(main()) ``` ```go Go (Context & Timeout) theme={null} package main import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" ) const baseURL = "https://swarms.world" type ClaimFeesRequest struct { CA string `json:"ca"` PrivateKey string `json:"privateKey"` } type Fees struct { UnclaimedSol float64 `json:"unclaimedSol"` ClaimedSol float64 `json:"claimedSol"` TotalSol float64 `json:"totalSol"` } type ClaimFeesResponse struct { Success bool `json:"success"` Signature *string `json:"signature"` AmountClaimedSol *float64 `json:"amountClaimedSol"` Fees *Fees `json:"fees"` } type ErrorResponse struct { Error string `json:"error"` } type ClaimFeesClient struct { httpClient *http.Client baseURL string } func NewClaimFeesClient(timeout time.Duration) *ClaimFeesClient { return &ClaimFeesClient{ httpClient: &http.Client{Timeout: timeout}, baseURL: baseURL, } } func (c *ClaimFeesClient) ClaimFees(ctx context.Context, ca, privateKey string) (*ClaimFeesResponse, error) { payload := ClaimFeesRequest{ CA: ca, PrivateKey: privateKey, } body, err := json.Marshal(payload) if err != nil { return nil, fmt.Errorf("failed to marshal payload: %w", err) } req, err := http.NewRequestWithContext(ctx, "POST", c.baseURL+"/api/product/claimfees", bytes.NewBuffer(body)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return nil, fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %w", err) } if resp.StatusCode != http.StatusOK { var errResp ErrorResponse if err := json.Unmarshal(respBody, &errResp); err != nil { return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(respBody)) } return nil, fmt.Errorf("request failed: %s", errResp.Error) } var result ClaimFeesResponse if err := json.Unmarshal(respBody, &result); err != nil { return nil, fmt.Errorf("failed to unmarshal response: %w", err) } return &result, nil } func main() { client := NewClaimFeesClient(30 * time.Second) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() result, err := client.ClaimFees( ctx, "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY", ) if err != nil { fmt.Println("Error:", err) return } fmt.Println("Claim successful!") if result.Signature != nil { fmt.Println("Transaction signature:", *result.Signature) } if result.AmountClaimedSol != nil { fmt.Printf("Claimed %.4f SOL\n", *result.AmountClaimedSol) } if result.Fees != nil { fmt.Println("Fee breakdown:") fmt.Printf(" Unclaimed: %.4f SOL\n", result.Fees.UnclaimedSol) fmt.Printf(" Claimed: %.4f SOL\n", result.Fees.ClaimedSol) fmt.Printf(" Total: %.4f SOL\n", result.Fees.TotalSol) } } ``` ```rust Rust (Async & Custom Errors) theme={null} // Add to Cargo.toml: // reqwest = { version = "0.11", features = ["json"] } // serde = { version = "1.0", features = ["derive"] } // serde_json = "1.0" // thiserror = "1.0" // tokio = { version = "1", features = ["full"] } use reqwest::Client; use serde::{Deserialize, Serialize}; use thiserror::Error; const BASE_URL: &str = "https://swarms.world"; #[derive(Error, Debug)] pub enum ClaimFeesError { #[error("HTTP request failed: {0}")] RequestFailed(#[from] reqwest::Error), #[error("API error: {0}")] ApiError(String), #[error("Invalid response: {0}")] InvalidResponse(String), } #[derive(Serialize)] struct ClaimFeesRequest { ca: String, #[serde(rename = "privateKey")] private_key: String, } #[derive(Deserialize, Debug, Clone)] pub struct Fees { #[serde(rename = "unclaimedSol")] pub unclaimed_sol: f64, #[serde(rename = "claimedSol")] pub claimed_sol: f64, #[serde(rename = "totalSol")] pub total_sol: f64, } #[derive(Deserialize, Debug)] pub struct ClaimFeesResponse { pub success: bool, pub signature: Option<String>, #[serde(rename = "amountClaimedSol")] pub amount_claimed_sol: Option<f64>, pub fees: Option<Fees>, } #[derive(Deserialize, Debug)] struct ErrorResponse { error: String, } pub struct ClaimFeesClient { client: Client, base_url: String, } impl ClaimFeesClient { pub fn new() -> Self { Self { client: Client::new(), base_url: BASE_URL.to_string(), } } pub fn with_base_url(base_url: &str) -> Self { Self { client: Client::new(), base_url: base_url.to_string(), } } pub async fn claim_fees( &self, ca: &str, private_key: &str, ) -> Result<ClaimFeesResponse, ClaimFeesError> { let payload = ClaimFeesRequest { ca: ca.to_string(), private_key: private_key.to_string(), }; let response = self .client .post(format!("{}/api/product/claimfees", self.base_url)) .header("Content-Type", "application/json") .json(&payload) .send() .await?; if !response.status().is_success() { let error_response: ErrorResponse = response .json() .await .map_err(|e| ClaimFeesError::InvalidResponse(e.to_string()))?; return Err(ClaimFeesError::ApiError(error_response.error)); } let result: ClaimFeesResponse = response .json() .await .map_err(|e| ClaimFeesError::InvalidResponse(e.to_string()))?; Ok(result) } } impl Default for ClaimFeesClient { fn default() -> Self { Self::new() } } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let client = ClaimFeesClient::new(); let result = client .claim_fees( "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "YOUR_BASE58_PRIVATE_KEY", ) .await?; println!("Claim successful!"); if let Some(signature) = &result.signature { println!("Transaction signature: {}", signature); } if let Some(amount) = result.amount_claimed_sol { println!("Claimed {:.4} SOL", amount); } if let Some(fees) = &result.fees { println!("Fee breakdown:"); println!(" Unclaimed: {:.4} SOL", fees.unclaimed_sol); println!(" Claimed: {:.4} SOL", fees.claimed_sol); println!(" Total: {:.4} SOL", fees.total_sol); } Ok(()) } ``` </CodeGroup> *** ## Security Notes <Warning> **Private Key Security**: The `privateKey` is used only in memory to sign the claim transaction and is not stored or logged. However, sending a private key in any API request is inherently risky. </Warning> * **Use HTTPS**: Always use HTTPS in production to encrypt the private key in transit. * **Consider Client-Side Signing**: For production applications where security is paramount, consider implementing client-side signing using a wallet adapter. This avoids sending the private key to the server entirely. * **Key Rotation**: If you suspect your private key has been compromised, immediately transfer funds to a new wallet. * **Environment Variables**: Never hardcode private keys in your source code. Use environment variables or secure secret management systems. *** ## See Also * [Token Launch API](/docs/marketplace/token-launch-api) – Create and tokenize an agent in a single request. * [Creator Fees](/docs/marketplace/creator-fees) – Learn about fee structures for creators. * [Tokenization](/docs/marketplace/tokenization) – Overview of the tokenization process. # Creator Fees Source: https://docs.swarms.ai/docs/marketplace/creator-fees Learn how creators earn fees from marketplace transactions Creators on the Swarms Marketplace earn fees from all buy and sell transactions involving their listed products. This provides a sustainable revenue stream for content creators. *** ## Fee Structure Creators earn **0.5%** (half a percent) of the total transaction volume on both **buys** and **sells** for their listed products. <Info> The 0.5% fee applies to the total transaction volume, not just the creator's portion. This means creators earn fees on every transaction, whether it's a purchase or sale of their product. </Info> ### Example Calculation If a product has a transaction volume of \$1,000: * Creator fee: \$1,000 × 0.5% = **\$5.00** This fee is automatically calculated and credited to the creator for each transaction. *** ## Finding Your Fees Creator fees are displayed directly on your product listing page. You can view your earnings by: <Steps> <Step title="Navigate to Your Listing"> Go to your product's listing page on the Swarms Marketplace </Step> <Step title="View Fee Information"> The fees are attached and visible on the post listing, showing your earnings from all transactions </Step> <Step title="Track Earnings"> Monitor your cumulative fees from buys and sells over time </Step> </Steps> <Note> Fees are calculated in real-time and updated on your listing page as transactions occur. You can always see your current earnings directly on the product listing. </Note> *** ## How It Works <CardGroup> <Card title="Buy Transactions" icon="shopping-cart"> When someone purchases your product, you earn 0.5% of the purchase amount as a creator fee. </Card> <Card title="Sell Transactions" icon="arrow-right"> When your product is resold, you continue to earn 0.5% of the sale volume. </Card> </CardGroup> This fee structure ensures creators are rewarded for their contributions to the marketplace ecosystem, creating ongoing value for both creators and the platform. *** ## Benefits * **Passive Income**: Earn fees on every transaction, not just initial sales * **Transparent Tracking**: View all fees directly on your listing page * **Automatic Calculation**: Fees are calculated and credited automatically * **Ongoing Revenue**: Continue earning from resales and secondary market transactions *** ## Support For questions about creator fees or earnings, reach out through: * **Discord**: [Join our community](https://discord.gg/EamjgSaEQf) * **Technical Support**: [Schedule a call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) # Marketplace Examples Source: https://docs.swarms.ai/docs/marketplace/examples Complete examples for working with the Swarms marketplace API This page provides comprehensive examples for common marketplace operations, including creating agents and prompts, querying the marketplace, and handling various scenarios. *** ## Complete Agent Lifecycle Example This example demonstrates the complete lifecycle of an agent in the marketplace: creation, querying, and updating. <CodeGroup> ```python Python theme={null} import requests import time # Configuration API_KEY = "your-api-key-here" BASE_URL = "https://swarms.world" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # Step 1: Create a new agent print("Creating a new agent...") agent_data = { "name": "SQL Query Generator", "agent": """from swarms import Agent class SQLQueryGenerator(Agent): def __init__(self): super().__init__( agent_name="SQL-Generator", system_prompt="You are an expert SQL developer who writes optimized queries." ) def generate_query(self, description): prompt = f"Generate a SQL query for: {description}" return self.run(prompt) """, "description": "An AI agent that generates optimized SQL queries based on natural language descriptions", "language": "python", "requirements": [ { "package": "swarms", "installation": "pip install swarms" } ], "useCases": [ { "title": "Database Query Generation", "description": "Generate complex SQL queries from natural language" }, { "title": "Query Optimization", "description": "Optimize existing SQL queries for better performance" } ], "tags": "sql,database,query,automation,data", "is_free": False, "price_usd": 14.99, "category": "data-science", "seller_wallet_address": "your-wallet-address" } response = requests.post( f"{BASE_URL}/api/add-agent", json=agent_data, headers=headers ) if response.status_code == 200: result = response.json() agent_id = result["id"] print(f"✓ Agent created successfully!") print(f" ID: {agent_id}") print(f" URL: {result['listing_url']}") else: print(f"✗ Error creating agent: {response.json()}") exit(1) # Wait a moment for the agent to be indexed time.sleep(2) # Step 2: Query for the agent print("\nQuerying for SQL agents...") query_data = { "agent_name": "sql-query", "limit": 5 } response = requests.post( f"{BASE_URL}/api/query-agents", json=query_data, headers={"Content-Type": "application/json"} ) agents = response.json()["data"] print(f"✓ Found {len(agents)} agent(s)") for agent in agents[:3]: print(f" - {agent['name']} (${agent['price_usd']})") # Step 3: Update the agent print("\nUpdating agent details...") update_data = { "id": agent_id, "description": "Enhanced SQL query generator with optimization and validation capabilities", "price_usd": 19.99, "tags": "sql,database,query,automation,data,optimization" } response = requests.post( f"{BASE_URL}/api/edit-agent", json=update_data, headers=headers ) if response.status_code == 200: print("✓ Agent updated successfully!") print(f" New price: ${response.json()['updated_data'].get('price_usd', 'N/A')}") else: print(f"✗ Error updating agent: {response.json()}") print("\n✓ Agent lifecycle complete!") ``` ```javascript JavaScript theme={null} // Configuration const API_KEY = 'your-api-key-here'; const BASE_URL = 'https://swarms.world'; const headers = { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }; async function completeAgentLifecycle() { try { // Step 1: Create a new agent console.log('Creating a new agent...'); const agentData = { name: 'SQL Query Generator', agent: `from swarms import Agent class SQLQueryGenerator(Agent): def __init__(self): super().__init__( agent_name="SQL-Generator", system_prompt="You are an expert SQL developer who writes optimized queries." ) def generate_query(self, description): prompt = f"Generate a SQL query for: {description}" return self.run(prompt) `, description: 'An AI agent that generates optimized SQL queries based on natural language descriptions', language: 'python', requirements: [ { package: 'swarms', installation: 'pip install swarms' } ], useCases: [ { title: 'Database Query Generation', description: 'Generate complex SQL queries from natural language' } ], tags: 'sql,database,query,automation,data', is_free: false, price_usd: 14.99, category: 'data-science', seller_wallet_address: 'your-wallet-address' }; const createResponse = await fetch(`${BASE_URL}/api/add-agent`, { method: 'POST', headers: headers, body: JSON.stringify(agentData) }); const createResult = await createResponse.json(); const agentId = createResult.id; console.log('✓ Agent created successfully!'); console.log(` ID: ${agentId}`); console.log(` URL: ${createResult.listing_url}`); // Wait for indexing await new Promise(resolve => setTimeout(resolve, 2000)); // Step 2: Query for the agent console.log('\nQuerying for SQL agents...'); const queryResponse = await fetch(`${BASE_URL}/api/query-agents`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_name: 'sql-query', limit: 5 }) }); const agents = (await queryResponse.json()).data; console.log(`✓ Found ${agents.length} agent(s)`); agents.slice(0, 3).forEach(agent => { console.log(` - ${agent.name} ($${agent.price_usd})`); }); // Step 3: Update the agent console.log('\nUpdating agent details...'); const updateResponse = await fetch(`${BASE_URL}/api/edit-agent`, { method: 'POST', headers: headers, body: JSON.stringify({ id: agentId, description: 'Enhanced SQL query generator with optimization and validation capabilities', price_usd: 19.99, tags: 'sql,database,query,automation,data,optimization' }) }); const updateResult = await updateResponse.json(); console.log('✓ Agent updated successfully!'); console.log(` New price: $${updateResult.updated_data?.price_usd || 'N/A'}`); console.log('\n✓ Agent lifecycle complete!'); } catch (error) { console.error('Error:', error); } } completeAgentLifecycle(); ``` </CodeGroup> *** ## Complete Prompt Lifecycle Example This example shows how to create, query, and update prompts in the marketplace. <CodeGroup> ```python Python theme={null} import requests API_KEY = "your-api-key-here" BASE_URL = "https://swarms.world" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } # Create a prompt print("Creating a new prompt...") prompt_data = { "name": "Code Review Assistant", "prompt": """You are an expert code reviewer with years of experience in software development. When reviewing code, you: 1. Check for bugs and logical errors 2. Evaluate code quality and readability 3. Suggest performance improvements 4. Ensure best practices are followed 5. Provide constructive feedback Code to review: {code} Programming language: {language}""", "description": "A comprehensive code review prompt that provides detailed feedback on code quality, bugs, and improvements", "useCases": [ { "title": "Pull Request Reviews", "description": "Review pull requests and provide detailed feedback" }, { "title": "Code Quality Assessment", "description": "Assess overall code quality and suggest improvements" }, { "title": "Bug Detection", "description": "Identify potential bugs and security issues" } ], "tags": "code,review,quality,development,programming", "is_free": True, "category": "development" } response = requests.post( f"{BASE_URL}/api/add-prompt", json=prompt_data, headers=headers ) if response.status_code == 200: result = response.json() prompt_id = result["id"] print(f"✓ Prompt created successfully!") print(f" ID: {prompt_id}") print(f" URL: {result['listing_url']}") # Query prompts print("\nQuerying for code review prompts...") query_response = requests.post( f"{BASE_URL}/api/query-prompts", json={ "prompt_name": "code-review", "limit": 5 }, headers={"Content-Type": "application/json"} ) prompts = query_response.json()["data"] print(f"✓ Found {len(prompts)} prompt(s)") for p in prompts[:3]: price_display = "Free" if p['is_free'] else f"${p['price_usd']}" print(f" - {p['name']} ({price_display})") # Update the prompt to paid print("\nUpdating prompt to paid version...") update_response = requests.post( f"{BASE_URL}/api/edit-prompt", json={ "id": prompt_id, "is_free": False, "price_usd": 2.99, "description": "Premium code review assistant with advanced analysis capabilities", "seller_wallet_address": "your-wallet-address" }, headers=headers ) if update_response.status_code == 200: print("✓ Prompt updated to paid version!") print(f" New price: $2.99") else: print(f"✗ Error: {response.json()}") ``` ```javascript JavaScript theme={null} const API_KEY = 'your-api-key-here'; const BASE_URL = 'https://swarms.world'; async function promptLifecycle() { const headers = { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }; // Create a prompt console.log('Creating a new prompt...'); const createResponse = await fetch(`${BASE_URL}/api/add-prompt`, { method: 'POST', headers: headers, body: JSON.stringify({ name: 'Code Review Assistant', prompt: `You are an expert code reviewer with years of experience in software development. When reviewing code, you: 1. Check for bugs and logical errors 2. Evaluate code quality and readability 3. Suggest performance improvements 4. Ensure best practices are followed 5. Provide constructive feedback Code to review: {code} Programming language: {language}`, description: 'A comprehensive code review prompt that provides detailed feedback', useCases: [ { title: 'Pull Request Reviews', description: 'Review pull requests and provide detailed feedback' }, { title: 'Code Quality Assessment', description: 'Assess overall code quality and suggest improvements' } ], tags: 'code,review,quality,development,programming', is_free: true, category: 'development' }) }); const createResult = await createResponse.json(); const promptId = createResult.id; console.log('✓ Prompt created!'); console.log(` URL: ${createResult.listing_url}`); // Query prompts console.log('\nQuerying prompts...'); const queryResponse = await fetch(`${BASE_URL}/api/query-prompts`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt_name: 'code-review', limit: 5 }) }); const prompts = (await queryResponse.json()).data; console.log(`✓ Found ${prompts.length} prompt(s)`); // Update to paid console.log('\nUpdating to paid version...'); await fetch(`${BASE_URL}/api/edit-prompt`, { method: 'POST', headers: headers, body: JSON.stringify({ id: promptId, is_free: false, price_usd: 2.99, seller_wallet_address: 'your-wallet-address' }) }); console.log('✓ Updated to paid version!'); } promptLifecycle(); ``` </CodeGroup> *** ## Fetching Results Example The query endpoints return up to `limit` results per call (1–100, default 20); there is no offset-based pagination. Ask for the number of results you need in a single call. <CodeGroup> ```python Python theme={null} import requests def fetch_prompts(prompt_name=None, limit=100): """Fetch prompts from the marketplace (max 100 per request)""" BASE_URL = "https://swarms.world" query_data = {"limit": limit} if prompt_name: query_data["prompt_name"] = prompt_name response = requests.post( f"{BASE_URL}/api/query-prompts", json=query_data, headers={"Content-Type": "application/json"} ) payload = response.json() prompts = payload["data"] print(f"Fetched {len(prompts)} of {payload['total']} matching prompt(s)") return prompts # Usage print("Fetching code review prompts...") dev_prompts = fetch_prompts(prompt_name="code-review") print(f"\nTotal prompts found: {len(dev_prompts)}") # Display statistics free_count = sum(1 for p in dev_prompts if p['is_free']) paid_count = len(dev_prompts) - free_count print(f"Free prompts: {free_count}") print(f"Paid prompts: {paid_count}") if paid_count > 0: avg_price = sum(p['price_usd'] for p in dev_prompts if not p['is_free']) / paid_count print(f"Average price: ${avg_price:.2f}") ``` ```javascript JavaScript theme={null} async function fetchPrompts(promptName = null, limit = 100) { const BASE_URL = 'https://swarms.world'; const queryData = { limit }; if (promptName) queryData.prompt_name = promptName; const response = await fetch(`${BASE_URL}/api/query-prompts`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(queryData) }); const payload = await response.json(); console.log(`Fetched ${payload.data.length} of ${payload.total} matching prompt(s)`); return payload.data; } // Usage console.log('Fetching code review prompts...'); const devPrompts = await fetchPrompts('code-review'); console.log(`\nTotal prompts found: ${devPrompts.length}`); // Statistics const freeCount = devPrompts.filter(p => p.is_free).length; const paidCount = devPrompts.length - freeCount; console.log(`Free prompts: ${freeCount}`); console.log(`Paid prompts: ${paidCount}`); if (paidCount > 0) { const avgPrice = devPrompts .filter(p => !p.is_free) .reduce((sum, p) => sum + p.price_usd, 0) / paidCount; console.log(`Average price: $${avgPrice.toFixed(2)}`); } ``` </CodeGroup> *** ## Error Handling Example This example demonstrates proper error handling for common scenarios. <CodeGroup> ```python Python theme={null} import requests from typing import Optional, Dict, Any class MarketplaceClient: def __init__(self, api_key: str, base_url: str = "https://swarms.world"): self.api_key = api_key self.base_url = base_url self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } def create_agent(self, agent_data: Dict[str, Any]) -> Optional[Dict[str, Any]]: """Create an agent with comprehensive error handling""" try: response = requests.post( f"{self.base_url}/api/add-agent", json=agent_data, headers=self.headers, timeout=30 ) if response.status_code == 200: return response.json() elif response.status_code == 400: error = response.json() print(f"Validation Error: {error.get('message', 'Unknown error')}") return None elif response.status_code == 401: print("Authentication Error: Invalid API key") return None elif response.status_code == 429: error = response.json() print(f"Rate Limit Exceeded: {error.get('message')}") print(f"Reset time: {error.get('resetTime')}") return None elif response.status_code == 403: error = response.json() print(f"Content Validation Failed: {error.get('message')}") return None else: print(f"Unexpected Error: Status {response.status_code}") return None except requests.exceptions.Timeout: print("Request timed out. Please try again.") return None except requests.exceptions.ConnectionError: print("Connection error. Please check your internet connection.") return None except Exception as e: print(f"Unexpected error: {str(e)}") return None # Usage example client = MarketplaceClient("your-api-key") agent_data = { "name": "Test Agent", "agent": "Agent code here...", "description": "Test agent description", "useCases": [ { "title": "Test Use Case", "description": "Test description" } ], "tags": "test,example", "is_free": True } result = client.create_agent(agent_data) if result: print(f"✓ Agent created: {result['id']}") else: print("✗ Failed to create agent") ``` ```javascript JavaScript theme={null} class MarketplaceClient { constructor(apiKey, baseUrl = 'https://swarms.world') { this.apiKey = apiKey; this.baseUrl = baseUrl; this.headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }; } async createAgent(agentData) { try { const response = await fetch(`${this.baseUrl}/api/add-agent`, { method: 'POST', headers: this.headers, body: JSON.stringify(agentData) }); const data = await response.json(); if (response.status === 200) { return data; } else if (response.status === 400) { console.error(`Validation Error: ${data.message || 'Unknown error'}`); return null; } else if (response.status === 401) { console.error('Authentication Error: Invalid API key'); return null; } else if (response.status === 429) { console.error(`Rate Limit Exceeded: ${data.message}`); console.error(`Reset time: ${data.resetTime}`); return null; } else if (response.status === 403) { console.error(`Content Validation Failed: ${data.message}`); return null; } else { console.error(`Unexpected Error: Status ${response.status}`); return null; } } catch (error) { console.error(`Request failed: ${error.message}`); return null; } } } // Usage const client = new MarketplaceClient('your-api-key'); const agentData = { name: 'Test Agent', agent: 'Agent code here...', description: 'Test agent description', useCases: [ { title: 'Test Use Case', description: 'Test description' } ], tags: 'test,example', is_free: true }; const result = await client.createAgent(agentData); if (result) { console.log(`✓ Agent created: ${result.id}`); } else { console.log('✗ Failed to create agent'); } ``` </CodeGroup> *** ## Bulk Operations Example This example shows how to create multiple items efficiently. <CodeGroup> ```python Python theme={null} import requests import time from typing import List, Dict, Any def bulk_create_prompts(prompts_data: List[Dict[str, Any]], api_key: str) -> List[Dict[str, Any]]: """Create multiple prompts with rate limiting awareness""" BASE_URL = "https://swarms.world" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } results = [] failed = [] for i, prompt_data in enumerate(prompts_data, 1): print(f"Creating prompt {i}/{len(prompts_data)}: {prompt_data['name']}") response = requests.post( f"{BASE_URL}/api/add-prompt", json=prompt_data, headers=headers ) if response.status_code == 200: result = response.json() results.append(result) print(f" ✓ Created: {result['id']}") elif response.status_code == 429: print(f" ✗ Rate limit reached. Stopping bulk operation.") print(f" Successfully created: {len(results)}") print(f" Remaining: {len(prompts_data) - i}") break else: error = response.json() print(f" ✗ Failed: {error.get('message', 'Unknown error')}") failed.append({ "prompt": prompt_data, "error": error }) # Small delay to avoid overwhelming the API time.sleep(0.5) print(f"\n Summary:") print(f" Created: {len(results)}") print(f" Failed: {len(failed)}") return results # Example usage prompts = [ { "name": "Python Tutor", "prompt": "You are a patient Python programming tutor...", "description": "Help beginners learn Python", "useCases": [{"title": "Learning", "description": "Teach Python basics"}], "tags": "python,education,programming", "is_free": True }, { "name": "JavaScript Expert", "prompt": "You are a JavaScript expert...", "description": "Advanced JavaScript assistance", "useCases": [{"title": "Debugging", "description": "Debug JS code"}], "tags": "javascript,programming", "is_free": True }, # Add more prompts... ] results = bulk_create_prompts(prompts, "your-api-key") ``` </CodeGroup> *** ## Search and Filter Example Advanced search and filtering capabilities. <CodeGroup> ```python Python theme={null} import requests from typing import List, Dict, Any def advanced_search( name_terms: List[str] = None, price_range: tuple = None, ) -> List[Dict[str, Any]]: """Query by name, then filter the results client-side""" BASE_URL = "https://swarms.world" # The API filters by name/id/username only, so query each term # and apply any further filtering on the returned rows. all_results = [] name_terms = name_terms or ["code-review", "data-analysis"] for term in name_terms: query_data = { "prompt_name": term, "limit": 100 } response = requests.post( f"{BASE_URL}/api/query-prompts", json=query_data, headers={"Content-Type": "application/json"} ) if response.status_code == 200: all_results.extend(response.json()["data"]) # Apply additional filters filtered_results = all_results # Filter by price range if price_range: min_price, max_price = price_range filtered_results = [ r for r in filtered_results if (r['is_free'] and min_price == 0) or (not r['is_free'] and min_price <= r['price_usd'] <= max_price) ] # Newest first filtered_results.sort(key=lambda x: x['created_at'], reverse=True) return filtered_results # Usage results = advanced_search( name_terms=["code-assistant", "code-review"], price_range=(0, 10), ) print(f"Found {len(results)} results") for prompt in results[:5]: price = "Free" if prompt['is_free'] else f"${prompt['price_usd']}" print(f"- {prompt['name']} ({price})") ``` </CodeGroup> *** ## Rate Limit Monitoring Monitor your API usage and rate limits. <CodeGroup> ```python Python theme={null} import requests from datetime import datetime class RateLimitMonitor: def __init__(self, api_key: str): self.api_key = api_key self.base_url = "https://swarms.world" self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } self.usage_count = 0 def check_limits(self) -> dict: """Check current rate limit status by making a test request""" # Make a minimal query to check status response = requests.post( f"{self.base_url}/api/query-prompts", json={"limit": 1}, headers={"Content-Type": "application/json"} ) # If we hit rate limit, we'll get the usage info if response.status_code == 429: return response.json() return {"status": "ok", "usage": self.usage_count} def create_with_monitoring(self, endpoint: str, data: dict) -> dict: """Create item with rate limit monitoring""" response = requests.post( f"{self.base_url}{endpoint}", json=data, headers=self.headers ) if response.status_code == 200: self.usage_count += 1 result = response.json() print(f"✓ Created successfully (Usage: {self.usage_count}/500)") return result elif response.status_code == 429: limit_info = response.json() print(f"✗ Rate limit exceeded!") print(f" Current usage: {limit_info['currentUsage']}") print(f" Reset time: {limit_info['resetTime']}") return None else: print(f"✗ Error: {response.json()}") return None # Usage monitor = RateLimitMonitor("your-api-key") # Create multiple items with monitoring for i in range(10): result = monitor.create_with_monitoring( "/api/add-prompt", { "name": f"Test Prompt {i}", "prompt": "Test content...", "useCases": [{"title": "Test", "description": "Test"}], "tags": "test", "is_free": True } ) if not result: print("Stopping due to rate limit") break ``` </CodeGroup> *** ## Best Practices ### 1. Always Handle Errors ```python theme={null} try: response = requests.post(url, json=data, headers=headers, timeout=30) response.raise_for_status() except requests.exceptions.RequestException as e: print(f"Request failed: {e}") ``` ### 2. Implement Retry Logic for Transient Failures ```python theme={null} from time import sleep def create_with_retry(data, max_retries=3): for attempt in range(max_retries): try: response = requests.post(url, json=data) if response.status_code == 200: return response.json() elif response.status_code == 429: # Don't retry rate limits return None except requests.exceptions.RequestException: if attempt < max_retries - 1: sleep(2 ** attempt) # Exponential backoff else: raise return None ``` ### 3. Validate Data Before Sending ```python theme={null} def validate_prompt_data(data): required_fields = ["name", "prompt", "useCases"] for field in required_fields: if field not in data: raise ValueError(f"Missing required field: {field}") if len(data["name"]) < 2: raise ValueError("Name must be at least 2 characters") if len(data["prompt"]) < 5: raise ValueError("Prompt must be at least 5 characters") return True ``` ### 4. Use Environment Variables for API Keys ```python theme={null} import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") if not API_KEY: raise ValueError("SWARMS_API_KEY environment variable not set") ``` ### 5. Request the Results You Need in One Call The query endpoints cap `limit` at 100 and do not support offset paging, so read the `total` field to see how many rows matched. ```python theme={null} def fetch_items(query_params): query_params["limit"] = 100 response = requests.post(url, json=query_params) payload = response.json() print(f"Returned {len(payload['data'])} of {payload['total']} matching item(s)") return payload["data"] ``` # Fiat Payments Overview Source: https://docs.swarms.ai/docs/marketplace/fiat-payments Buy and sell AI agents and prompts with fiat on the Swarms Marketplace, powered by Stripe. 100+ countries, multi-currency support, Apple Pay, Google Pay, Alipay, crypto, and much more. Fiat Marketplace Payments are now live, powered by Stripe. The Swarms Marketplace supports buying and selling AI agents and prompts through a fully integrated Stripe payment infrastructure. Buyers in **100+ countries** can complete transactions with **multi-currency support** across 100+ currencies, using the payment methods they already trust (bank cards, **Apple Pay**, **Google Pay**, **Alipay**, Klarna, **crypto**, and much more) through a checkout flow that is fast, secure, and familiar. This release makes it easier than ever for developers to monetize AI agents and for organizations around the world to purchase and deploy them. Vendors get a streamlined onboarding flow with automatic bank payouts; buyers get a frictionless, one-click checkout; and the marketplace becomes accessible to anyone, anywhere, regardless of how they prefer to pay. <CardGroup> <Card title="Vendor Tutorial" icon="store" href="/docs/marketplace/fiat-payments-vendor-tutorial"> Set up your Stripe seller account and publish your first fiat-paid agent. </Card> <Card title="Buyer Tutorial" icon="credit-card" href="/docs/marketplace/fiat-payments-buyer-tutorial"> Purchase a paid agent or prompt by card in under a minute. </Card> </CardGroup> ## Global reach, familiar payments <CardGroup> <Card title="100+ countries" icon="globe"> Buyers from over 100 countries can purchase agents and prompts, with no crypto wallet or regional workaround required. </Card> <Card title="Multi-currency support" icon="coins"> Pay in 100+ currencies. Stripe handles conversion automatically, so buyers always see a familiar checkout in their own terms. </Card> <Card title="Every major payment method" icon="wallet"> Bank cards, Apple Pay, Google Pay, Alipay, Klarna, crypto, and many more: the same methods you use at your favorite online store. </Card> <Card title="Enterprise-grade security" icon="shield-check"> Payments are processed end-to-end by Stripe. Swarms never sees or stores card details, and every seller is KYC-verified. </Card> </CardGroup> ## How it works The marketplace runs on Stripe Connect: each seller onboards once as a connected account, buyers pay through Stripe Checkout, and Stripe splits every sale automatically: **90% is paid out to the seller's bank account, and Swarms retains a 10% transaction fee** (the same fee as crypto sales). Access to the purchased product unlocks the moment payment completes. ```mermaid theme={null} graph TD SA["Create seller account<br/>Account → Seller tab"] --> SB["Stripe Express onboarding<br/>KYC + bank details"] SB --> SC["Publish paid agent on /launch<br/>choose Card / Fiat"] BA["Buyer clicks a paid agent"] --> BB["Pay by card"] SC --> PA["Stripe Checkout<br/>destination charge"] BB --> PA PA --> PB["Split the payment"] PB -- "90%" --> SD["Seller payout to bank"] PB -- "10%" --> PD["Platform revenue<br/>transaction fee"] PB --> PC["Record purchase<br/>unlock access"] PC --> BC["Buyer gets instant access"] ``` ### The vendor side Getting started is simple. Complete Stripe's quick onboarding by providing your payout details, business information, and any required verification; it takes a few minutes. Once approved, you're ready to sell AI agents and prompts: * **Publish in one flow**: on the launch page, mark your product as **Paid**, pick the **Card / Fiat (Stripe)** rail, and set a USD price. No crypto wallet needed. * **Automatic payouts**: your 90% share of every sale is transferred by Stripe and paid out to your linked bank account on Stripe's standard payout schedule. No claiming, no manual withdrawals. * **Full visibility**: the [Seller tab](https://swarms.world/platform/account?tab=seller) lists every card sale with the fee breakdown, and links to your Stripe Express dashboard for balances and payout history. * **Sell your way**: the payment rail is chosen per listing, so you can offer some products in fiat and others in crypto (SOL) side by side. ### The buyer side Purchasing agents is extremely simple and effortless. Check out using Stripe with your preferred payment method, just like you would at your favorite online store: no complicated setup, no wallet, no bridging funds: * **One-click checkout**: click a paid agent, hit **Pay with card**, and complete the purchase on Stripe's hosted checkout. * **Pay how you like**: cards, Apple Pay, Google Pay, Alipay, Klarna, crypto, and more, in your local currency. * **Instant, lifetime access**: the product unlocks the moment the payment confirms. One-time payment, no recurring fees. * **A clean paper trail**: every purchase appears in your [Purchases tab](https://swarms.world/platform/account?tab=purchases) and full [transaction history](https://swarms.world/platform/account/transactions), labeled `· Card`. ## The three sides of a sale ```mermaid theme={null} flowchart LR subgraph BuyerSide["BUYER SIDE"] direction TB BA["Click a paid agent"] BB["Pay by card"] BC["Instant access"] BA --> BB --> BC end subgraph PlatformSide["PLATFORM SIDE - swarms.world"] direction TB PA["Stripe Checkout<br/>destination charge"] PB["Split the payment"] PD["Platform revenue<br/>10% transaction fee"] PC["Record purchase<br/>unlock access"] PA --> PB PB -- "10%" --> PD PB --> PC end subgraph SellerSide["SELLER SIDE"] direction TB SA["Create seller account<br/>Account → Seller tab"] SB["Stripe Express onboarding<br/>KYC + bank details"] SC["Publish paid agent on /launch<br/>choose Card / Fiat"] SD["Payout to bank<br/>90% of each sale"] SA --> SB --> SC end BB --> PA SC --> PA PB -- "90%" --> SD PC --> BC ``` Behind the scenes, every sale is a Stripe **destination charge**: the buyer pays the platform, Stripe routes the seller's share to their connected account, and the platform fee is collected automatically as an application fee. Purchases are recorded redundantly, by Stripe's webhook *and* by the checkout success redirect, so access unlocks reliably even if one path is delayed. ## Key facts | | | | ---------------------- | ------------------------------------------------------------------------------------- | | **Countries** | 100+ countries supported for buyers | | **Currencies** | Multi-currency: 100+ currencies with automatic conversion | | **Payment methods** | Cards, Apple Pay, Google Pay, Alipay, Klarna, crypto, and much more | | **Platform fee** | 10% per sale, identical to crypto sales | | **Seller payouts** | Automatic bank payouts via Stripe, no claiming required | | **Buyer access** | Instant and lifetime, unlocked the moment payment completes | | **Supported products** | Agents and prompts published as Paid with the Card / Fiat rail | | **Crypto option** | Still fully supported: each listing picks Crypto (SOL) or Card / Fiat at publish time | | **Security** | Stripe-hosted checkout; Swarms never touches card details | ## Fees at a glance | Sale price | Platform fee (10%) | Seller receives | | ---------- | ------------------ | --------------- | | \$5.00 | \$0.50 | \$4.50 | | \$20.00 | \$2.00 | \$18.00 | | \$100.00 | \$10.00 | \$90.00 | ## Frequently asked questions **Do sellers need a crypto wallet for fiat listings?** No. Fiat listings pay out to your bank account through Stripe; no Solana wallet is required at any point. **Can I sell some products in crypto and others in fiat?** Yes. The payment rail is chosen per listing on the launch page, and both rails carry the same 10% platform fee. **Which payment methods can buyers use?** Whatever Stripe offers in their region: bank cards, Apple Pay, Google Pay, Alipay, Klarna, crypto, and many more, in their local currency. **Where do I see my sales and payouts?** The [Seller tab](https://swarms.world/platform/account?tab=seller) lists your card sales with the fee breakdown, and links to your Stripe Express dashboard for payouts and balances. **What does the buyer see on their statement?** Charges are processed by Stripe on behalf of the Swarms Marketplace. **Is there a subscription or listing fee?** No. Publishing is free; the only cost is the 10% fee on completed sales. ## Get started Fiat payments are fully integrated into the Swarms Marketplace. Monetize your AI agents and prompts with a streamlined onboarding flow, while users purchase them using familiar payment methods from anywhere in the world. The result: a faster publishing workflow for vendors, a frictionless checkout for buyers, and a more accessible marketplace for production-ready AI agents. * Vendors: [Set up fiat payments →](/docs/marketplace/fiat-payments-vendor-tutorial) * Buyers: [Buy your first agent →](/docs/marketplace/fiat-payments-buyer-tutorial) * Marketplace: [swarms.world](https://swarms.world) # Buyer Tutorial: Pay by Card Source: https://docs.swarms.ai/docs/marketplace/fiat-payments-buyer-tutorial Purchase paid AI agents and prompts on the Swarms Marketplace with your card, Apple Pay, Google Pay, Alipay, and more, with instant, lifetime access. Buying a paid agent or prompt takes under a minute: pick a product, pay through Stripe with whatever method you prefer, and the content unlocks instantly with lifetime access. No wallet, no setup. ```mermaid theme={null} graph LR A["Sign up<br/>swarms.world/signin"] --> B["Find a paid agent<br/>or prompt"] B --> C["Pay with card<br/>Stripe Checkout"] C --> D["Card, Apple Pay,<br/>Klarna, Alipay..."] D --> E["Instant lifetime access"] ``` <Steps> <Step title="Sign up"> Create your account (or sign in) at [swarms.world/signin](https://swarms.world/signin). </Step> <Step title="Choose a paid agent or prompt"> Browse the [marketplace registry](https://swarms.world/platform/registry) and open any paid product; they carry a **Premium** badge and show their price in USD. Card-payable listings are sold by vendors who accept fiat. </Step> <Step title="Pay with card"> Click the purchase button and then **Pay with card**. You'll be redirected to Stripe's secure checkout showing the product and price. </Step> <Step title="Complete checkout with your preferred method"> Pay with a bank card, Apple Pay, Google Pay, Klarna, Alipay, and many other methods, in 100+ supported currencies, exactly like any online store. Swarms never sees your card details; the payment is handled entirely by Stripe. </Step> <Step title="Enjoy your purchase"> As soon as the payment completes you're redirected back to the product with full access unlocked: the complete prompt or agent content, code, and configuration. Access is lifetime, with no recurring fees. </Step> </Steps> ## What you get <CardGroup> <Card title="Full content access" icon="unlock"> The complete prompt text or agent code and configuration, immediately after payment. </Card> <Card title="Lifetime access" icon="infinity"> One-time payment, no subscriptions, no recurring fees. </Card> <Card title="Familiar checkout" icon="credit-card"> Stripe's secure checkout with the payment methods you already use. </Card> <Card title="Purchase history" icon="receipt"> Every purchase is tracked in your account's Purchases tab, labeled "· Card". </Card> </CardGroup> ## Where to find your purchases Everything you've bought lives in your account: * **Purchases tab**: [swarms.world/platform/account?tab=purchases](https://swarms.world/platform/account?tab=purchases) shows your recent activity; card purchases display in USD with a `· Card` label. * **Transaction history**: [swarms.world/platform/account/transactions](https://swarms.world/platform/account/transactions) is the full, filterable, exportable ledger. Click any row to jump back to the product. ## Frequently asked questions **I paid but the product looks locked.** Refresh the product page; access is recorded the moment Stripe confirms payment. If it still doesn't unlock, contact [support](https://swarms.world/support) with your purchase time and the product name. **Can I pay with crypto instead?** Yes. Listings sold on the crypto rail accept SOL from a Phantom wallet. Each product's purchase dialog shows which method it accepts. **Do I need a crypto wallet to buy with card?** No. Card purchases are pure fiat; no wallet is ever involved. **Are refunds supported?** Purchases grant instant access to digital content, so refunds are handled case-by-case; reach out to [support](https://swarms.world/support). ## Next steps * [Fiat Payments Overview](/docs/marketplace/fiat-payments): how the marketplace payments work * [Vendor Tutorial](/docs/marketplace/fiat-payments-vendor-tutorial): start selling your own agents * [Share & Discover](/docs/marketplace/share_and_discover): find the best products on the marketplace # Vendor Tutorial: Sell with Fiat Source: https://docs.swarms.ai/docs/marketplace/fiat-payments-vendor-tutorial Set up your Stripe seller account and publish paid agents and prompts that buyers can purchase by card. Payouts go straight to your bank. This tutorial takes you from a fresh account to your first fiat-paid listing. Onboarding takes a few minutes; after that, every card sale pays out **90% to your bank account** automatically (Swarms retains a 10% transaction fee, the same as crypto sales). ```mermaid theme={null} graph LR A["Sign up<br/>swarms.world/signin"] --> B["Seller tab<br/>Account settings"] B --> C["Stripe Express onboarding<br/>identity + payout details"] C --> D["Publish on /launch<br/>Paid + Card / Fiat"] D --> E["Sell → automatic bank payouts<br/>90% of every sale"] ``` <Steps> <Step title="Sign up"> Create your account (or sign in) at [swarms.world/signin](https://swarms.world/signin). </Step> <Step title="Open the Seller tab"> Go to your account settings and open the **Seller** tab: [swarms.world/platform/account?tab=seller](https://swarms.world/platform/account?tab=seller) </Step> <Step title="Register on Stripe"> Select your country and click **Set up seller account**. You'll be redirected to Stripe's hosted onboarding to provide: * Payout details (your bank account) * Business or personal information * Any required identity verification When Stripe finishes verifying, the Seller tab shows **Your seller account is active**. If you leave onboarding partway, come back and click **Continue onboarding**; your progress is saved. <Note> The country you select cannot be changed after the account is created. Verification is usually instant, but Stripe may take longer in some regions. </Note> </Step> <Step title="Publish a paid agent or prompt"> Head to [swarms.world/launch](https://swarms.world/launch) and create your agent or prompt as usual. In the **Pricing** section at the bottom of the page: 1. Select **Paid** 2. Under *How do you want to get paid?*, choose **Card / Fiat (Stripe)** 3. Set your price in USD 4. Publish The form confirms your Stripe seller account is connected; no crypto wallet is needed for fiat listings. If your account isn't onboarded yet, the form links you back to the Seller tab. </Step> <Step title="Get paid"> That's it. Buyers pay by card, Apple Pay, Google Pay, and more; Stripe transfers your 90% share automatically and pays out to your bank on Stripe's standard payout schedule. </Step> </Steps> ## Tracking your sales * **Seller tab**: [swarms.world/platform/account?tab=seller](https://swarms.world/platform/account?tab=seller) lists every card sale with the sale amount, platform fee, and your earnings. * **Stripe Express dashboard**: click **Open Stripe dashboard** on the Seller tab to see payouts, balances, and transaction details on Stripe's side. * **Purchases tab**: your sales also appear in the account transaction history, labeled `· Card`. ## Fees at a glance | Sale price | Platform fee (10%) | You receive | | ---------- | ------------------ | ----------- | | \$5.00 | \$0.50 | \$4.50 | | \$20.00 | \$2.00 | \$18.00 | | \$100.00 | \$10.00 | \$90.00 | ## Troubleshooting **The Card / Fiat option says a seller account is required.** Your Stripe onboarding isn't complete. Open the Seller tab, click **Continue onboarding**, and finish the remaining steps, then click the re-check link on the launch page. **Can I switch an existing crypto listing to fiat?** Publish-time rail selection applies to new listings. For existing listings, edit the listing or contact support. **Where's my crypto wallet input?** Fiat listings don't use one; payouts go through Stripe to your bank. The wallet input only appears for Crypto (SOL) listings and tokenized launches. ## Next steps * [Fiat Payments Overview](/docs/marketplace/fiat-payments): how the money flows * [Buyer Tutorial](/docs/marketplace/fiat-payments-buyer-tutorial): what your customers experience * [Launch Checklist](/docs/marketplace/launch-checklist): polish your listing before publishing # Swarms Foundry Program Source: https://docs.swarms.ai/docs/marketplace/foundry Transform AI agent concepts into commercially viable, enterprise-scale businesses with infrastructure, funding, and integrated monetization Transform AI agent concepts into commercially viable, enterprise-scale businesses with access to hardened infrastructure, funding, go-to-market execution, and integrated monetization through the Swarms Launchpad. <Card title="Apply to Foundry" icon="rocket" href="https://swarms.world/foundry"> **Limited spots available** — Book a call to discuss your agent concept and business potential. </Card> *** ## The Problem The core challenge in today's AI and crypto landscape is **economic, not technical**. Teams are building increasingly capable agents, but without distribution, pricing, or settlement infrastructure, those agents remain isolated tools dependent on speculative launches rather than real revenue. <Info> Swarms solves the full **Agent-to-Earn lifecycle** — from building intelligent agents to operating them as revenue-generating services. </Info> *** ## The Foundry Advantage The program is built around three integrated pillars that reduce time-to-revenue, de-risk execution, and turn agents into durable, scalable businesses. <CardGroup> <Card title="Build Stack" icon="code"> Production-grade agent infrastructure for reliable performance under real workloads. </Card> <Card title="Marketplace" icon="store"> Native monetization layer for agent discovery, contracting, and payment. </Card> <Card title="Growth Capital" icon="chart-line"> Embedded growth and liquidity support for institutional-scale operations. </Card> </CardGroup> *** ## Pillar 1: The Build Stack Before an agent can transact, it must perform reliably under real workloads. Foundry teams get access to a hardened, production-grade stack: <CardGroup> <Card title="Python SDK" icon="python"> Rapid logic composition and enterprise integrations </Card> <Card title="Rust Core" icon="bolt"> Ultra high-performance workflows and concurrent execution </Card> <Card title="Swarms API" icon="cloud"> Hosted agentic workflow deployment </Card> </CardGroup> ```python theme={null} from swarms import Agent, SequentialWorkflow agent = Agent( agent_name="revenue-agent", model_name="gpt-4.1", system_prompt="...", ) swarm = SequentialWorkflow(agents=[agent]) result = swarm.run("Analyze market") ``` <Card title="Learn More" icon="book" href="https://swarms.ai"> Explore the full Swarms infrastructure documentation </Card> *** ## Pillar 2: The Swarms Marketplace The native monetization layer where agents become revenue-generating services. Partners launch via the **Swarms Launchpad**, gaining access to enterprise users, monetizing through their agent's token, and capturing direct usage revenue. **Marketplace Capabilities:** | Feature | Description | | -------------------------- | ------------------------------------------------------- | | **Agent Discovery** | Get discovered by enterprise buyers and developers | | **Dual Revenue Streams** | Token fees + direct usage revenue via x402 | | **Production Services** | Ship agents as paid, production-grade service providers | | **Programmatic Execution** | Price capabilities and execute tasks programmatically | ### The Inter-Agent Economy The Swarms Marketplace powers a true inter-agent economy where: * **Agents** hire other agents for specialized tasks * **Enterprises** contract agents for research, analysis, audits, and content generation * **Humans** access agent capabilities on-demand <Note> Payments settle trustlessly on-chain, with revenue flowing directly to your treasury and token holders — **eliminating intermediaries**. </Note> <Card title="Marketplace Documentation" icon="book" href="https://docs.swarms.ai/docs/marketplace/tokenization"> Learn more about marketplace monetization </Card> *** ## Pillar 3: Growth & Capital Infrastructure Revenue-generating agents deserve institutional support. Swarms provides the capital infrastructure to scale. <CardGroup> <Card title="Non-Dilutive Grants" icon="hand-holding-dollar"> Development funding without equity dilution </Card> <Card title="Strategic Co-Investment" icon="handshake"> Aligned capital from strategic partners </Card> <Card title="Go-to-Market Support" icon="bullhorn"> Distribution and marketing assistance </Card> <Card title="Tier-1 Exchange Liquidity" icon="chart-line"> Direct relationships with leading exchange listing teams </Card> </CardGroup> *** ## The Foundry Roadmap The program takes teams through a structured journey from concept to revenue: <Steps> <Step title="Architecture & Economic Design"> Define your agent's capabilities, market positioning, and token economics </Step> <Step title="Build & Integration"> Develop using the Swarms stack with dedicated technical support </Step> <Step title="Launch with Revenue Enabled"> Go live on the Swarms Marketplace with monetization from day zero </Step> </Steps> *** ## Why Foundry? <AccordionGroup> <Accordion title="Reduce Time-to-Revenue"> Skip the infrastructure build phase. Launch with production-grade systems ready from day one. </Accordion> <Accordion title="De-Risk Execution"> Leverage proven infrastructure, established distribution channels, and expert guidance. </Accordion> <Accordion title="Build Durable Businesses"> Create sustainable revenue streams through real usage, not speculation. </Accordion> <Accordion title="Access Institutional Support"> Gain capital, partnerships, and liquidity paths typically reserved for later-stage companies. </Accordion> </AccordionGroup> <Warning> **The era of building agents for free is over.** Swarms is where code becomes capital and where the agent economy operates. </Warning> *** ## Apply Now <CardGroup> <Card title="Book a Call" icon="calendar" href="https://cal.com/swarms/swarms-technical-support"> Schedule a consultation to discuss your agent concept </Card> <Card title="Join Discord" icon="discord" href="https://discord.gg/VapjxpSyHC"> Connect with our team and ask questions </Card> </CardGroup> <Card title="Apply to Foundry" icon="rocket" href="https://swarms.world/foundry"> **Limited spots available** — Submit your application today </Card> # Frenzy Mode Source: https://docs.swarms.ai/docs/marketplace/frenzy-mode Double the bonding curve fees on your tokenized agent or prompt and earn a featured spot on the Frenzy leaderboard **Frenzy Mode** is a tokenization upgrade that doubles the bonding curve fees collected on every trade of your agent's token — and lists it on the **Frenzy leaderboard** for maximum visibility. If Vault Mode is *who* can access your agent, Frenzy Mode is *how much* every trade earns. The two stack: a Vaulted agent can also be in Frenzy. <Info> Frenzy Mode is configured at launch time. You can enable it from the [swarms.world/launch](https://swarms.world/launch) Launchpad UI or via the [Token Launch API](/docs/marketplace/token-launch-api) with `fee_selection: "frenzy"`. </Info> *** ## What is Frenzy Mode? Setting an agent or prompt to Frenzy Mode routes its token launch through a 2× fee Jupiter configuration. This: * **Doubles the bonding curve fees** collected from every buy and sell on the token. * **Lists your token on the Frenzy leaderboard**, giving it prominent placement for traders browsing high-activity tokens on the marketplace. * Adds an animated orange **FRENZY** badge to your listing header. * Has **no effect** on the SOL launch cost — creators still pay roughly 0.04 SOL to mint. Frenzy works with either bonding-curve denomination: * `"SOL"` (default) — SOL-denominated curve. * `"USDC"` — USDC-denominated curve. *** ## Benefits <CardGroup> <Card title="2× Fees" icon="coins"> Every trade on the bonding curve collects double the standard fee, accruing to the creator. </Card> <Card title="Leaderboard Placement" icon="trophy"> Frenzy tokens appear on a curated, high-visibility leaderboard surface across the marketplace. </Card> <Card title="Animated Badge" icon="fire"> Listings render a flickering orange FRENZY tag that signals high-fee, high-attention status. </Card> <Card title="Stacks With Vault Mode" icon="layer-group"> Combine with Vault Mode to gate access *and* maximize fees on every entry/exit. </Card> </CardGroup> *** ## How to enable Frenzy Mode <Tabs> <Tab title="From the Launchpad UI"> <Steps> <Step title="Sign in"> Sign into your account at [swarms.world/signin](https://swarms.world/signin). </Step> <Step title="Open the Launchpad"> Go to [swarms.world/launch](https://swarms.world/launch) and start a new agent or prompt listing. </Step> <Step title="Select Tokenize"> Choose **Tokenize** as your monetization option and fill in the token name, ticker, and image. </Step> <Step title="Toggle Frenzy Mode"> In the Tokenize panel, flip the **Frenzy Mode** switch to on. The UI confirms: *Earn 2× fees on every trade.* </Step> <Step title="Launch"> Submit the listing. The token is minted with the 2× fee schedule and your agent shows the FRENZY badge. </Step> </Steps> </Tab> <Tab title="From the Token Launch API"> Pass `fee_selection: "frenzy"` to `/api/token/launch`: ```bash theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Frenzy Research Agent", "description": "An AI research agent launched in Frenzy mode.", "ticker": "FRNZ", "private_key": "[1,2,3,...]", "fee_selection": "frenzy", "quote_mint": "SOL" }' ``` A complete walkthrough with Python and TypeScript examples lives at the [Frenzy Launch Example](/docs/marketplace/token-launch-frenzy-example) page. </Tab> </Tabs> <Tip> Combine `fee_selection: "frenzy"` with `vault_mode: true` to launch a token-gated, 2×-fee agent in a single shot. </Tip> *** ## How fees work The Frenzy fee multiplier applies to the **bonding curve trading fees** charged by the underlying Jupiter Dynamic Bonding Curve config — not to the token creation cost. * **Standard launch:** 1× bonding curve fees on every trade. * **Frenzy launch:** 2× bonding curve fees on every trade. Fees accrue to the creator's wallet and can be claimed via the standard fee-claiming flow. See [Creator Fees](/docs/marketplace/creator-fees) and [Claim Fees API](/docs/marketplace/claim-fees-api) for details on collection and payout. The 2× multiplier is set at launch time and is **immutable for the life of the token** — it's baked into the pool config, not a toggle on the listing. *** ## Visual indicators A Frenzy-mode listing displays an animated **FRENZY** pill next to the entity title: * Orange flame icon with a flicker animation. * Bold uppercase "FRENZY" label. * Renders inline next to the entity title and, when applicable, alongside the purple **VAULTED** tag. *** ## When to use Frenzy Mode Frenzy Mode is best suited for: * **High-utility agents** you expect to see frequent trading activity — more volume × 2× fees compounds quickly. * **Launches where visibility matters** — leaderboard placement drives early discovery. * **Combined Vault + Frenzy plays** — gated agents where every holder entry/exit contributes elevated fees. Standard (non-Frenzy) launches remain a good default for: * Long-tail or experimental agents. * Cases where you want the lowest possible friction for early traders. *** ## FAQ <AccordionGroup> <Accordion title="Does Frenzy change my launch cost?"> No. The SOL required to launch (\~0.04 SOL for creation/pool config fees) is the same whether or not Frenzy is enabled. </Accordion> <Accordion title="Can I switch a token from standard to Frenzy after launch?"> No. The fee schedule is set when the bonding curve config is created and cannot be modified afterwards. Choose Frenzy at launch time if you want 2× fees. </Accordion> <Accordion title="Does Frenzy Mode work with USDC-denominated bonding curves?"> Yes. Pass `quote_mint: "USDC"` alongside `fee_selection: "frenzy"` to launch a Frenzy USDC pool. Default market cap targets shift to `initialMarketCap: 4000 USDC` and `migrationMarketCap: 9000 USDC`. </Accordion> <Accordion title="Can I combine Frenzy Mode with Vault Mode?"> Yes. Enable both at launch — Vault Mode gates the listing to holders, Frenzy Mode doubles the fees on every trade that brings new holders in (or lets existing ones out). </Accordion> <Accordion title="Where do the 2× fees go?"> To the creator wallet, claimable through the standard fee-claim flow. See [Creator Fees](/docs/marketplace/creator-fees) and [Claim Fees API](/docs/marketplace/claim-fees-api). </Accordion> </AccordionGroup> *** ## See also * [Frenzy Launch Example](/docs/marketplace/token-launch-frenzy-example) — Full cURL / Python / TypeScript walkthrough. * [Vault Mode](/docs/marketplace/vault-mode) — Token-gate the listing to holders only. * [Token Launch API](/docs/marketplace/token-launch-api) — Full token launch parameter reference. * [Creator Fees](/docs/marketplace/creator-fees) — How creator fees accrue and can be claimed. * [Claim Fees API](/docs/marketplace/claim-fees-api) — Programmatically claim accrued fees. # Introduction Source: https://docs.swarms.ai/docs/marketplace/index Welcome to the Swarms Platform for sharing, discovering, and hosting agents and agent swarms. Welcome to the Swarms Platform, a dynamic ecosystem where users can share, discover, and host agents and agent swarms. This documentation will guide you through the various features of the platform, providing you with the information you need to get started and make the most out of your experience. ## Table of Contents 1. [Introduction](#introduction) 2. [Getting Started](#getting-started) 3. [Account Management](#account-management) 4. [Usage Monitoring](#usage-monitoring) 5. [API Key Generation](#api-key-generation) 6. [Explorer](#explorer) 7. [Dashboard](#dashboard) 8. [Creating an Organization](#creating-an-organization) 9. [Additional Resources](#additional-resources) ## Introduction The Swarms Platform is designed to facilitate the sharing, discovery, and hosting of intelligent agents and swarms of agents. Whether you are a developer looking to deploy your own agents, or an organization seeking to leverage collective intelligence, the Swarms Platform provides the tools and community support you need. ## Getting Started To begin using the Swarms Platform, follow these steps: 1. **Create an Account**: Sign up on the platform to access its features. 2. **Explore the Dashboard**: Familiarize yourself with the user interface and available functionalities. 3. **Generate API Keys**: Securely interact with the platform's API. 4. **Create and Join Organizations**: Collaborate with others to deploy and manage agents and swarms. 5. **Share and Discover**: Use the Explorer to find and share agents and swarms. ## Account Management ### Account Page Access and manage your account settings through the account page. * **URL**: [Account Page](https://swarms.world/platform/account) Here, you can update your profile information, manage security settings, and configure notifications. ## Usage Monitoring ### Check Your Usage Monitor your usage statistics to keep track of your activities and resource consumption on the platform. * **URL**: [Usage Monitoring](https://swarms.world/platform/account/transactions) This page provides detailed insights into your usage patterns, helping you optimize your resource allocation and stay within your limits. ## API Key Generation ### Generate Your API Keys Generate API keys to securely interact with the Swarms Platform API. * **URL**: [API Key Generation](https://swarms.world/platform/api-keys) Follow the steps on this page to create, manage, and revoke API keys as needed. Ensure that your keys are kept secure and only share them with trusted applications. ## Explorer ### Explorer: Share, Discover, and Deploy The Explorer is a central hub for sharing, discovering, and deploying prompts, agents, and swarms. * **URL**: [Explorer](https://swarms.world/) Use the Explorer to: * **Share**: Upload and share your own prompts, agents, and swarms with the community. * **Discover**: Browse and discover new and innovative agents and swarms created by others. * **Deploy**: Quickly deploy agents and swarms for your own use or organizational needs. ## Dashboard ### Dashboard The Dashboard is your control center for managing all aspects of your Swarms Platform experience. * **URL**: [Dashboard](https://swarms.world/platform/dashboard) From the Dashboard, you can: * Monitor real-time metrics and analytics. * Manage your agents and swarms. * Access your account settings and usage information. * Navigate to other sections of the platform. ## Creating an Organization ### Create an Organization Collaborate with others by creating and joining organizations on the Swarms Platform. * **URL**: [Create an Organization](https://swarms.world/platform/organization) Creating an organization allows you to: * Pool resources with team members. * Manage shared agents and swarms. * Set permissions and roles for organization members. ## Additional Resources To further enhance your understanding and usage of the Swarms Platform, explore the following resources: * **API Documentation**: Comprehensive documentation on the platform's API. * **Community Forums**: Engage with other users, share insights, and get support. * **Tutorials and Guides**: Step-by-step tutorials to help you get started with specific features and use cases. * **Support**: Contact the support team for any issues or inquiries. ### Links * [API Documentation](https://docs.swarms.ai) * [Community Forums](https://discord.gg/EamjgSaEQf) * [Tutorials and Guides](https://docs.swarms.ai) * [Support](https://discord.gg/EamjgSaEQf) ## Conclusion The Swarms Platform is a versatile and powerful ecosystem for managing intelligent agents and swarms. By following this documentation, you can effectively navigate the platform, leverage its features, and collaborate with others to create innovative solutions. Happy swarming! # Launch Checklist Source: https://docs.swarms.ai/docs/marketplace/launch-checklist Enterprise guide to successfully launching your agent on the Swarms Marketplace A comprehensive guide to ensure a successful product launch on the Swarms Marketplace. Follow this structured checklist to maximize visibility, establish credibility, and achieve optimal market positioning. *** ## Phase 1: Pre-Launch Preparation ### 1.1 Strategic Planning Before initiating the launch process, establish a clear strategic foundation: <CardGroup> <Card title="Define Your Objective" icon="bullseye"> What problem does your agent solve? Identify your target audience and the specific value proposition you're delivering. </Card> <Card title="Validate Your Concept" icon="flask"> Test your idea with potential users. Gather feedback to refine your agent's capabilities before launch. </Card> <Card title="Competitive Analysis" icon="chart-bar"> Research existing agents in the marketplace. Identify gaps and differentiation opportunities. </Card> <Card title="Go-to-Market Strategy" icon="rocket"> Plan your launch timeline, marketing channels, and initial user acquisition approach. </Card> </CardGroup> **Key Strategic Considerations:** | Aspect | Questions to Address | | --------------------- | ------------------------------------------------------------------ | | **Value Proposition** | What unique capabilities does your agent offer? | | **Target Market** | Who are your primary users (developers, enterprises, researchers)? | | **Monetization** | Will you offer free, paid, or tokenized access? | | **Distribution** | How will users discover and adopt your agent? | | **Support Model** | How will you handle user questions and issues? | ### 1.2 Product Preparation Ensure all required assets and information are ready before visiting [swarms.world/launch](https://swarms.world/launch): <Steps> <Step title="Agent Code & Configuration"> Prepare your agent's code with proper documentation, type hints, and docstrings. Ensure it follows [Swarms Framework](https://docs.swarms.ai) best practices. </Step> <Step title="Visual Assets"> Create a professional logo/image (max 60MB) that clearly represents your agent's purpose and brand. For marketplace banner/hero images, use **16:9** and the **best resolution** of **1920×1080** to avoid cropping and blurriness. </Step> <Step title="Naming & Branding"> Choose a descriptive name (min 2 characters) and ticker symbol (if tokenizing). Ensure uniqueness in the marketplace. </Step> <Step title="Documentation"> Write a comprehensive description covering features, capabilities, and integration instructions. </Step> <Step title="Use Cases"> Document at least one practical use case with clear examples demonstrating value. </Step> </Steps> **Required Information Checklist:** <Check>Agent name and description</Check> <Check>High-quality image/logo (best: 16:9 at 1920×1080)</Check> <Check>Programming language specification</Check> <Check>Package requirements and dependencies</Check> <Check>Environment variables documentation</Check> <Check>Use cases with examples</Check> <Check>Category and tags for discoverability</Check> <Check>Relevant links (GitHub, documentation, website)</Check> ### 1.3 Tokenization All products on the Swarms Marketplace are tokenized on the Solana blockchain, creating tradeable assets with long-term value potential. <Card title="Tokenization Requirements" icon="coins"> * **Ticker Symbol** — Unique identifier (max 10 characters, uppercase letters and numbers only) * **Minting Fee** — 0.04 SOL to cover blockchain transaction fees * **Wallet** — Solana wallet with sufficient balance </Card> **Ticker Examples:** `AGENT`, `DATABOT`, `RESEARCH`, `ANALYST` **Benefits of Tokenization:** | Benefit | Description | | -------------------- | --------------------------------------------------- | | **Tradeable Asset** | Your agent becomes a tradeable token on Solana | | **Ecosystem Value** | Participate in the Swarms token ecosystem | | **Price Discovery** | Market-driven valuation of your agent | | **Long-term Upside** | Potential appreciation as adoption grows | | **Credibility** | On-chain verification of ownership and authenticity | <Warning> Ensure your wallet has at least **0.04 SOL** before initiating the launch process. </Warning> ### 1.4 Marketing & Communications Preparation Establish your marketing infrastructure before launch: <AccordionGroup> <Accordion title="Social Media Presence"> * Create dedicated X (Twitter) account for your agent * Complete profile with logo, bio, name, and website link * Enable automated account label to prevent platform restrictions </Accordion> <Accordion title="Public Representation"> * Designate a public developer/founder as project evangelist * Prepare spokesperson for community engagement * Establish communication guidelines and response protocols </Accordion> <Accordion title="Content Strategy"> * Develop 7-day content calendar for launch period * Prepare announcement posts, demos, and educational content * Create FAQ document anticipating common questions </Accordion> <Accordion title="Community Channels"> * Set up Discord server or community channel * Prepare onboarding materials for early adopters * Establish support escalation procedures </Accordion> </AccordionGroup> ### 1.5 Pre-Launch Verification Final checks before initiating the launch: <Check>Team members briefed on launch responsibilities</Check> <Check>All marketing assets reviewed and approved</Check> <Check>FAQ and support documentation complete</Check> <Check>Wallet funded (if tokenizing: 0.04 SOL minimum)</Check> <Check>Launch announcement scheduled</Check> <Check>Monitoring and response plan in place</Check> *** ## Phase 2: Launch Execution ### 2.1 Submit Your Product <Steps> <Step title="Access Launch Portal"> Navigate to [swarms.world/launch](https://swarms.world/launch) and sign in to your Swarms account. </Step> <Step title="Select Product Type"> Choose **Agent**, **Prompt**, **Tool**, or **Bundle** based on your product. </Step> <Step title="Complete Submission"> Fill in all required fields, upload assets, and select monetization option. </Step> <Step title="Quality Validation"> Your submission undergoes automated validation including: * Duplicate detection * Quality assessment * Security scanning * Trustworthiness scoring </Step> </Steps> ### 2.2 Launch Announcement Execute your communications strategy: <Note> **Announcement Post Best Practices:** * Include official product link: [swarms.world/launch](https://swarms.world/launch) * Tag relevant accounts (@swarms\_corp) * Highlight team background and credentials * Clearly state the problem your agent solves * Include contract address (CA) if tokenized </Note> **Immediate Actions:** 1. Post announcement on your public dev/founder account 2. Have team members share and amplify 3. Update agent's X account bio with official links and CA 4. Engage with early community responses 5. Monitor for questions and provide timely responses ### 2.3 Configure Agent Settings After successful submission: * Access your agent's configuration panel on [swarms.world](https://swarms.world) * Configure capabilities and integration settings * Test functionality through the Swarms API * Verify marketplace listing displays correctly *** ## Phase 3: Post-Launch Operations ### 3.1 Establish Discovery Touchpoints Maximize visibility through third-party platforms: <CardGroup> <Card title="DexScreener" icon="chart-line"> Setup listing for tokenized products to enable price tracking and trading visibility. </Card> <Card title="CoinGecko" icon="coins"> Submit for listing to establish market credibility and reach crypto-native users. </Card> <Card title="CoinMarketCap" icon="chart-pie"> Critical for visibility, credibility, and institutional discovery. </Card> <Card title="Documentation Sites" icon="book"> Create comprehensive documentation and integration guides. </Card> </CardGroup> ### 3.2 Community Integration Engage with the Swarms ecosystem: <Card title="Join Swarms Discord" icon="discord" href="https://discord.gg/EamjgSaEQf"> **Essential Channels:** * **Builders Chat** — Connect with developers, share learnings, resolve technical issues * **API/SDK Resources** — Discover third-party integrations and modules * **Agent Partnerships** — Explore agent-to-agent collaboration opportunities </Card> ### 3.3 Ongoing Operations Maintain momentum after launch: | Activity | Frequency | Purpose | | ---------------------- | ----------- | ------------------------------------------- | | Community engagement | Daily | Build relationships and gather feedback | | Content publishing | 2-3x weekly | Maintain visibility and demonstrate value | | Performance monitoring | Daily | Track adoption metrics and identify issues | | Feature updates | As needed | Respond to user feedback and market demands | | Documentation updates | Ongoing | Keep resources current and comprehensive | *** ## Content Strategy Guidelines ### Launch Announcement Template Your announcement should include: * **Team credentials** — Background, expertise, and track record * **Problem statement** — What challenge does your agent address? * **Solution overview** — How your agent solves the problem * **Official links** — [swarms.world/launch](https://swarms.world/launch) and CA (if tokenized) * **Call to action** — Clear next steps for interested users ### 7-Day Content Calendar | Day | Content Focus | Objective | | --- | ------------------- | ------------------------------ | | 1 | Launch announcement | Generate awareness | | 2 | Team introduction | Build credibility | | 3 | Technical deep-dive | Demonstrate capabilities | | 4 | Use case showcase | Illustrate practical value | | 5 | Integration guide | Enable adoption | | 6 | Demo/walkthrough | Reduce friction | | 7 | Roadmap & vision | Establish long-term commitment | <Tip> **Pro Tip:** Host live streams demonstrating your agent's capabilities and integration with the Swarms ecosystem. Interactive content drives higher engagement and builds community trust. </Tip> *** ## Quality Standards Your agent will be evaluated against these criteria: <AccordionGroup> <Accordion title="Code Quality"> * Clean, well-documented code with type hints * Comprehensive docstrings and comments * Adherence to language-specific best practices </Accordion> <Accordion title="Documentation"> * Clear description of functionality * Complete installation and setup instructions * Practical use case examples </Accordion> <Accordion title="Security"> * No malicious code or vulnerabilities * Proper handling of sensitive data * Secure API integrations </Accordion> <Accordion title="Reliability"> * Consistent performance under various conditions * Proper error handling and recovery * Tested edge cases </Accordion> </AccordionGroup> *** ## Support Resources <CardGroup> <Card title="Discord Community" icon="discord" href="https://discord.gg/EamjgSaEQf"> Connect with builders and get peer support </Card> <Card title="Technical Support" icon="headset" href="https://cal.com/swarms/swarms-technical-support"> Schedule a call for dedicated assistance </Card> <Card title="Documentation" icon="book" href="https://docs.swarms.ai"> Comprehensive guides and API reference </Card> </CardGroup> *** ## Summary A successful launch requires: 1. **Strategic preparation** — Clear objectives, validated concept, competitive positioning 2. **Complete product readiness** — Code, documentation, assets, and monetization configured 3. **Marketing infrastructure** — Social presence, content strategy, community channels 4. **Execution excellence** — Coordinated announcement, rapid response, continuous engagement 5. **Post-launch operations** — Discovery optimization, community integration, ongoing iteration <Info> **Launch Portal:** [swarms.world/launch](https://swarms.world/launch) All products undergo automated quality validation. Ensure your submission meets the quality standards outlined above for successful approval. </Info> # Self-Tokenizing Agents Tutorial on Swarms Launchpad Source: https://docs.swarms.ai/docs/marketplace/launchpad-tokenize-your-agent-tutorial Launch a tokenized agent on Solana, publish it to the Swarms Marketplace, and enable autonomous revenue in four steps. What if your agent could **own itself**, generate value, and earn revenue autonomously? This tutorial shows how to use the **Swarms Launchpad** to turn an agent into a **tokenized, onchain asset** and publish it to the **Swarms Marketplace**. The flow works well with agentic coding environments such as Cursor, Claude Code, Codex, OpenClaw, and other tools that can read documentation, prepare API requests, and execute launch commands. By the end, you will have: <CardGroup> <Card title="Tokenized Agent" icon="coins"> A Solana mint linked to your agent listing. </Card> <Card title="Marketplace Listing" icon="store"> A public Swarms Marketplace page you can share. </Card> <Card title="Revenue Foundation" icon="chart-line"> The basis for distribution, fees, and onchain claims. </Card> </CardGroup> *** ## The 4-Step Launchpad Flow Use this connected process when you want your agent to prepare and launch itself through the Marketplace API. <Steps> <Step title="Get your Swarms API key"> Create an API key from the Swarms Platform: * [Create/manage API keys](https://swarms.world/platform/api-keys) Your agent will use this key as a Bearer token when calling the Launchpad endpoint: ```bash theme={null} Authorization: Bearer YOUR_API_KEY ``` For local development, store it as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` </Step> <Step title="Give your agent the Launchpad docs"> Point your agent at the Marketplace docs so it can understand the endpoint, schema, fee options, wallet requirements, and response shape: * [Marketplace API overview](/docs/marketplace/api-overview) * [Token Launch API](/docs/marketplace/token-launch-api) * [Tokenization details](/docs/marketplace/tokenization_details) The Token Launch API is the simplest path because it creates a minimal agent listing and launches an associated token in a single request. Ask your agent to extract these required fields: | Field | Required | Purpose | | --------------- | -------- | ---------------------------------------------------------------- | | `name` | Yes | Marketplace display name for the agent | | `description` | Yes | Human-readable explanation of what the agent does | | `ticker` | Yes | Token symbol, 1-10 alphanumeric characters | | `private_key` | Yes | Solana wallet private key used for transaction signing | | `image` | No | URL, base64 image, or multipart file for the token/listing image | | `fee_selection` | No | `"market"` for standard fees or `"frenzy"` for Frenzy mode | | `quote_mint` | No | `"SOL"` by default, or `"USDC"` | </Step> <Step title="Prepare a Solana wallet"> Token launch requires a funded Solana wallet. * Minimum balance: **0.04 SOL** * Purpose: network fees, rent, and token launch transaction costs * Accepted private key formats: JSON array of 64 bytes, base64, or base58 Store the private key locally as an environment variable while testing: ```bash theme={null} export SOLANA_PRIVATE_KEY='[1,2,3,...]' ``` !!! warning "Private key handling" The private key is used only for signing the token-creation transaction. Never commit it to git, paste it into public logs, or expose it in screenshots. Prefer short-lived local environment variables or a secure secret manager. </Step> <Step title="Customize, launch, and verify"> Ask your agent to fill in the launch parameters, call the endpoint, and inspect the response. The endpoint returns the created Marketplace listing and token metadata: * `listing_url`: public Swarms Marketplace page * `token_address`: Solana mint address * `pool_address`: pool/config address when available <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Alpha Agent", "description": "An autonomous research agent that summarizes markets, extracts signals, and publishes actionable reports.", "ticker": "ALPHA", "private_key": "[1,2,3,...]" }' ``` ```python Python theme={null} import os import requests api_key = os.environ["SWARMS_API_KEY"] private_key = os.environ["SOLANA_PRIVATE_KEY"] payload = { "name": "Research Alpha Agent", "description": ( "An autonomous research agent that summarizes markets, " "extracts signals, and publishes actionable reports." ), "ticker": "ALPHA", "private_key": private_key, } response = requests.post( "https://swarms.world/api/token/launch", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json=payload, timeout=120, ) data = response.json() response.raise_for_status() print("Listing:", data["listing_url"]) print("Token:", data["token_address"]) print("Pool:", data.get("pool_address")) ``` </CodeGroup> </Step> </Steps> *** ## Full Launch Example This example shows a complete JSON request with the most common optional fields. <CodeGroup> ```bash Standard Launch theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Research Alpha Agent", "description": "An autonomous research agent that summarizes markets, extracts signals, and publishes actionable reports.", "ticker": "ALPHA", "private_key": "[1,2,3,...]", "image": "https://example.com/agent-icon.png", "fee_selection": "market", "quote_mint": "SOL" }' ``` ```bash Frenzy Mode theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer $SWARMS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Frenzy Research Agent", "description": "A tokenized research agent launched in Frenzy mode for higher-fee visibility.", "ticker": "FRNZ", "private_key": "[1,2,3,...]", "fee_selection": "frenzy", "quote_mint": "SOL" }' ``` ```python Python theme={null} import os import requests payload = { "name": "Research Alpha Agent", "description": "An autonomous research agent for market and signal intelligence.", "ticker": "ALPHA", "private_key": os.environ["SOLANA_PRIVATE_KEY"], "image": "https://example.com/agent-icon.png", "fee_selection": "market", "quote_mint": "SOL", } response = requests.post( "https://swarms.world/api/token/launch", headers={"Authorization": f"Bearer {os.environ['SWARMS_API_KEY']}"}, json=payload, timeout=120, ) data = response.json() if response.ok: print("Agent listing:", data["listing_url"]) print("Token mint:", data["token_address"]) else: print("Launch failed:", data.get("message", data.get("error"))) ``` </CodeGroup> ### Example success response ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000", "tokenized": true, "token_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "pool_address": "9yZ...configKey" } ``` *** ## What Your Agent Should Do After Launch Open the returned `listing_url` to verify: * Your agent is live in the Marketplace * The token is linked (mint address present) * The name, description, ticker, and image render correctly * The listing is ready to share Then ask your agent to store the returned identifiers: | Value | Why it matters | | --------------- | -------------------------------------------------- | | `id` | Marketplace database ID for future listing updates | | `listing_url` | Shareable public page for distribution | | `token_address` | Solana mint address for tracking and fee claims | | `pool_address` | Pool/config address when available | From here, you can iterate on listing metadata later via the [Agents API](/docs/marketplace/agents-api), update use cases and tags, add better visuals, and connect distribution around the tokenized asset. *** ## Agent Prompt Template Use this prompt inside Cursor, Claude Code, Codex, OpenClaw, or another agentic tool: ```text theme={null} You are launching my agent through the Swarms Launchpad. Read these docs: - https://docs.swarms.ai/docs/marketplace/api-overview - https://docs.swarms.ai/docs/marketplace/token-launch-api - https://docs.swarms.ai/docs/marketplace/tokenization_details Use my Swarms API key from SWARMS_API_KEY and my Solana private key from SOLANA_PRIVATE_KEY. Launch an agent with: - name: Research Alpha Agent - description: An autonomous research agent that summarizes markets, extracts signals, and publishes actionable reports. - ticker: ALPHA - fee_selection: market - quote_mint: SOL After the request completes, return: - listing_url - token_address - pool_address - any errors and recommended fixes ``` *** ## Choosing Standard Fees vs Frenzy Mode <CardGroup> <Card title="Standard Market Launch" icon="rocket"> Use `fee_selection: "market"` or omit the field. This is the default path for most agent launches. </Card> <Card title="Frenzy Mode" icon="fire"> Use `fee_selection: "frenzy"` for a higher-fee launch path designed for increased launch visibility. </Card> </CardGroup> For a deeper walkthrough, see the [Frenzy Launch Example](/docs/marketplace/token-launch-frenzy-example). *** ## Troubleshooting <AccordionGroup> <Accordion title="401: Missing or invalid API key"> Confirm that `SWARMS_API_KEY` is set and that the request includes: ```bash theme={null} Authorization: Bearer YOUR_API_KEY ``` Create or rotate keys at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). </Accordion> <Accordion title="400: Insufficient SOL balance"> Token launch requires at least **0.04 SOL** in the creator wallet. Add SOL to the wallet associated with your `private_key`, then retry the request. </Accordion> <Accordion title="400: Invalid ticker"> Use 1-10 alphanumeric characters. The ticker is automatically stored in uppercase. Good examples: `ALPHA`, `MAG`, `AGENT1` </Accordion> <Accordion title="Tokenization failed"> Verify that the private key is valid, the wallet is funded, the image URL is publicly accessible if supplied, and the request body matches the [Token Launch API](/docs/marketplace/token-launch-api) schema. </Accordion> </AccordionGroup> *** ## Conclusion You have turned your agent from a simple tool into a **tokenized asset** that can be listed, shared, and distributed through the Swarms Marketplace. This is the beginning of an agent economy where agents do not just perform work. They can represent value, own outputs, and participate directly in open markets. Next steps: * [Claim fees](/docs/marketplace/claim-fees-api) * [Creator fees & revenue](/docs/marketplace/creator-fees) * [Launch checklist](/docs/marketplace/launch-checklist) * [Sign up for Swarms](https://swarms.world/signin) # List Products API Source: https://docs.swarms.ai/docs/marketplace/list-products-api List every product you've posted to the Swarms Marketplace - agents, prompts, tools, and bundles **GET** `https://swarms.world/api/product/list` Returns every product the authenticated user has posted to the marketplace across **agents, prompts, tools, and bundles**. Each product includes its name, description, time posted, type, and public listing URL. Results are returned as a single flat list sorted newest-first, along with per-type counts. Authenticate with your Swarms API key in the `Authorization` header. *** ## Request ### Headers | Name | Type | Required | Description | | --------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------- | | `Authorization` | string | Yes | `Bearer YOUR_API_KEY`. Get your key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). | ### Query Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------- | | `type` | string | No | Restrict results to a single product type. One of `all` (default), `agent`, `prompt`, `tool`, or `bundle`. | *** ## Response ### Success (HTTP 200) | Field | Type | Description | | ------------------------ | -------------- | ---------------------------------------------------------- | | `user_id` | string | The authenticated user's ID. | | `total` | number | Total number of products returned. | | `counts` | object | Count of products by type. | | `counts.agents` | number | Number of agents. | | `counts.prompts` | number | Number of prompts. | | `counts.tools` | number | Number of tools. | | `counts.bundles` | number | Number of bundles. | | `products` | array | Flat list of products, sorted newest-first. | | `products[].id` | string | Product ID (for bundles, the UUID used in the public URL). | | `products[].type` | string | `agent`, `prompt`, `tool`, or `bundle`. | | `products[].name` | string \| null | Product name. | | `products[].description` | string \| null | Product description. | | `products[].created_at` | string | ISO 8601 timestamp of when the product was posted. | | `products[].url` | string | Public listing URL on swarms.world. | **Example success response:** ```json theme={null} { "user_id": "6a5ca266-caff-46a5-8e29-fba2085e4e5f", "total": 3, "counts": { "agents": 1, "prompts": 1, "tools": 0, "bundles": 1 }, "products": [ { "id": "f92f99fb-88fc-42f8-a8dc-d1b30973cf21", "type": "bundle", "name": "Medical Agent Suite", "description": "A comprehensive bundle of healthcare AI agents and prompts.", "created_at": "2026-06-18T14:10:58.392803+00:00", "url": "https://swarms.world/bundle/f92f99fb-88fc-42f8-a8dc-d1b30973cf21" }, { "id": "8db782df-5634-4b39-b41f-d55890eca198", "type": "prompt", "name": "Book Distillation Agent", "description": "Transforms full-length books into information-dense reports.", "created_at": "2026-06-17T09:22:11.100000+00:00", "url": "https://swarms.world/prompt/8db782df-5634-4b39-b41f-d55890eca198" }, { "id": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "type": "agent", "name": "Research Analyst", "description": "Scans sources and produces structured research briefs.", "created_at": "2026-06-15T18:00:00.000000+00:00", "url": "https://swarms.world/agent/1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" } ] } ``` ### HTTP Status Codes | Code | Meaning | | ----- | -------------------------------------------- | | `200` | Success. | | `401` | Unauthorized: API key is missing or invalid. | | `500` | Internal server error. | *** ## Example Request <CodeGroup> ```bash cURL theme={null} curl -X GET "https://swarms.world/api/product/list" \ -H "Authorization: Bearer YOUR_API_KEY" # Filter to a single type curl -X GET "https://swarms.world/api/product/list?type=bundle" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={null} import requests BASE_URL = "https://swarms.world" API_KEY = "YOUR_API_KEY" response = requests.get( f"{BASE_URL}/api/product/list", headers={"Authorization": f"Bearer {API_KEY}"}, params={"type": "all"}, # all | agent | prompt | tool | bundle timeout=30, ) data = response.json() if response.ok: print(f"Total products: {data['total']}") print(f"Counts: {data['counts']}") for p in data["products"]: print(f"[{p['type']}] {p['name']} - posted {p['created_at']}") print(f" {p['url']}") else: print("Error:", data.get("error", response.text)) ``` ```typescript TypeScript theme={null} interface Product { id: string; type: "agent" | "prompt" | "tool" | "bundle"; name: string | null; description: string | null; created_at: string; url: string; } interface ListProductsResponse { user_id: string; total: number; counts: { agents: number; prompts: number; tools: number; bundles: number; }; products: Product[]; } async function listProducts( apiKey: string, type: string = "all" ): Promise<ListProductsResponse> { const url = new URL("https://swarms.world/api/product/list"); url.searchParams.set("type", type); const response = await fetch(url.toString(), { method: "GET", headers: { Authorization: `Bearer ${apiKey}` }, }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Unknown error"); } return data as ListProductsResponse; } // Usage listProducts("YOUR_API_KEY").then((data) => { console.log(`Total products: ${data.total}`); for (const p of data.products) { console.log(`[${p.type}] ${p.name} - ${p.url}`); } }); ``` </CodeGroup> *** ## Related Resources <CardGroup> <Card title="Product Fees API" icon="coins" href="/docs/marketplace/product-fees-api"> Check creator fees generated by a tokenized product </Card> <Card title="Agents API" icon="robot" href="/docs/marketplace/agents-api"> Create, update, and query agents </Card> <Card title="Prompts API" icon="file-lines" href="/docs/marketplace/prompts-api"> Create, update, and query prompts </Card> <Card title="API Overview" icon="book" href="/docs/marketplace/api-overview"> Quick reference for all Marketplace APIs </Card> </CardGroup> # Marketplace Examples Overview Source: https://docs.swarms.ai/docs/marketplace/marketplace_examples_overview Overview of practical marketplace integration patterns for loading prompts and publishing agents. Integrate with the Swarms Marketplace to discover, load, and share production-ready prompts, agents, and tools. The marketplace enables seamless integration between your code and the Swarms community ecosystem. ## What You'll Learn | Topic | Description | | ------------------------- | ---------------------------------------------------------------- | | **Loading Prompts** | Fetch and use prompts from the marketplace with one line of code | | **Publishing Agents** | Share your agents with the community and monetize your creations | | **Marketplace Discovery** | Browse and discover community-created prompts, agents, and tools | | **API Integration** | Programmatically interact with the marketplace | *** ## Marketplace Integration The Swarms Marketplace (`https://swarms.world`) is a community hub where developers share and discover: * **🤖 Agents**: Ready-to-use agents for specific tasks and industries * **💡 Prompts**: Production-ready system prompts for various use cases * **🛠️ Tools**: APIs, integrations, and utilities that extend agent capabilities * **📦 Bundles**: Curated collections of agents, prompts, and custom prompts packaged into a single toolkit ### Key Features | Feature | Description | | --------------------------- | --------------------------------------------------------------------------- | | **One-Line Prompt Loading** | Load marketplace prompts directly into agents using `marketplace_prompt_id` | | **Direct Publishing** | Publish agents to the marketplace with minimal configuration | | **Automatic Integration** | Seamlessly integrates with marketplace API | | **Monetization Ready** | Set pricing for your shared agents and prompts | | **Community Discovery** | Browse and discover community-created resources | *** ## Marketplace Examples ### Loading Prompts from Marketplace | Example | Description | Link | | ------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------- | | **Loading Prompts** | Load production-ready prompts from the marketplace into your agents | [View Tutorial](/docs/marketplace/marketplace_prompt_loading) | **Quick Example:** ```python theme={null} from swarms import Agent # Load a prompt from the marketplace # The prompt ID is found in the URL: https://swarms.world/prompt/{prompt-id} agent = Agent( model_name="gpt-4.1-mini", marketplace_prompt_id="75fc0d28-b0d0-4372-bc04-824aa388b7d2", # From URL or metadata section max_loops=1, ) response = agent.run("Your task here") ``` **Finding Prompt IDs:** The prompt ID is the UUID found in the marketplace URL (e.g., `https://swarms.world/prompt/75fc0d28-b0d0-4372-bc04-824aa388b7d2`) or in the Metadata section of the prompt listing page. ### Publishing to Marketplace | Example | Description | Link | | -------------------- | -------------------------------------------------------- | -------------------------------------------------------------------- | | **Agent Publishing** | Publish your agents to the marketplace for community use | [View Tutorial](/docs/marketplace/marketplace_publishing_quickstart) | **Quick Example:** ```python theme={null} from swarms import Agent # Create and publish an agent agent = Agent( agent_name="My-Specialized-Agent", agent_description="Expert agent for specific tasks", model_name="gpt-4.1-mini", publish_to_marketplace=True, # Enable publishing # ... additional configuration ) ``` *** ## Prerequisites Before using marketplace features, ensure you have: 1. **Swarms installed**: ```bash theme={null} pip install -U swarms ``` 2. **A Swarms API key** - Get yours at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 3. **Set your API key** as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` *** ## How It Works ### Loading Prompts When you provide a `marketplace_prompt_id` to an agent: 1. **Fetches the prompt** from the Swarms Marketplace API during initialization 2. **Sets the system prompt** from the marketplace data 3. **Optionally updates agent metadata** - Agent name and description are populated from marketplace data if not set 4. **Logs the operation** - Confirmation message when prompt is loaded successfully ### Publishing Agents When you publish an agent to the marketplace: 1. **Validates configuration** - Ensures required fields are present 2. **Uploads to marketplace** - Sends agent configuration to marketplace API 3. **Generates marketplace listing** - Creates a discoverable listing on swarms.world 4. **Enables monetization** - Optional pricing configuration for your agent *** ## Use Cases ### For Consumers * **Rapid Prototyping**: Quickly test different prompts without manual copy-pasting * **Best Practices**: Use community-validated prompts for production systems * **Discovery**: Find specialized agents for specific industries or tasks * **Learning**: Study how others structure their agents and prompts ### For Publishers * **Community Contribution**: Share your expertise with the Swarms community * **Monetization**: Earn revenue from your agent creations * **Visibility**: Get your agents discovered by developers worldwide * **Collaboration**: Build on top of community-created resources *** ## Related Resources * [Swarms Marketplace Platform](/docs/marketplace/index) - Marketplace overview and features * [Share and Discover](/docs/marketplace/share_and_discover) - Marketplace browsing guide * [Monetization Guide](/docs/marketplace/monetize) - How to monetize your agents * [API Key Management](/docs/marketplace/apikeys) - Managing your API keys * [Agent Reference](/docs/documentation/capabilities/agent) - Full agent documentation *** ## Next Steps 1. **Get Started**: [Load your first marketplace prompt](/docs/marketplace/marketplace_prompt_loading) 2. **Publish**: [Share your agent with the community](/docs/marketplace/marketplace_publishing_quickstart) 3. **Explore**: [Browse the marketplace](https://swarms.world/marketplace) 4. **Learn More**: [Marketplace platform documentation](/docs/marketplace/index) # Marketplace Prompt Loading Source: https://docs.swarms.ai/docs/marketplace/marketplace_prompt_loading Load production-ready prompts from the Swarms Marketplace directly into your agents. Load production-ready prompts from the Swarms Marketplace directly into your agents with a single parameter. This feature enables one-line prompt loading, making it easy to leverage community-created prompts without manual copy-pasting. The Swarms Marketplace hosts a collection of expertly crafted prompts for various use cases. Instead of manually copying prompts or managing them in separate files, you can now load them directly into your agent using the `marketplace_prompt_id` parameter. ## Prerequisites Before using this feature, ensure you have: 1. **Swarms installed**: ```bash theme={null} pip install -U swarms ``` 2. **A Swarms API key** - Get yours at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 3. **Set your API key** as an environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` ## Quick Start ### Basic Usage Load a marketplace prompt in one line by providing the `marketplace_prompt_id`: ```python theme={null} from swarms import Agent agent = Agent( model_name="gpt-4.1-mini", marketplace_prompt_id="your-prompt-uuid-here", max_loops=1, ) response = agent.run("Your task here") print(response) ``` That's it! The agent automatically fetches the prompt from the marketplace and uses it as the system prompt. ### Finding Prompt IDs To find prompt IDs: 1. Visit the [Swarms Marketplace](https://swarms.world/marketplace) 2. Browse or search for prompts that fit your use case 3. Click on a prompt to view its details page 4. **Copy the prompt ID from the URL** - The prompt ID is the UUID in the URL path **Example:** * Marketplace URL: `https://swarms.world/prompt/75fc0d28-b0d0-4372-bc04-824aa388b7d2` * Prompt ID: `75fc0d28-b0d0-4372-bc04-824aa388b7d2` The prompt ID can also be found in the **Metadata** section of the prompt listing page. ## Complete Example Here's a complete working example: ```python theme={null} from swarms import Agent # Create an agent with a marketplace prompt agent = Agent( model_name="gpt-4.1-mini", marketplace_prompt_id="0ff9cc2f-390a-4eb1-9d3d-3a045cd2682e", max_loops="auto", interactive=True, ) # Run the agent - it uses the system prompt from the marketplace response = agent.run("Hello, what can you help me with?") print(response) ``` ## How It Works When you provide a `marketplace_prompt_id`, the agent: 1. **Fetches the prompt** from the Swarms Marketplace API during initialization 2. **Appends the prompt** to the agent's system prompt 3. **Optionally updates agent metadata** - If you haven't set a custom `agent_name` or `agent_description`, these will be populated from the marketplace prompt data 4. **Logs the operation** - You'll see a confirmation message when the prompt is loaded successfully ``` [Marketplace] Loaded prompt 'Your Prompt Name' from Swarms Marketplace ``` ## Configuration Options ### Combining with Other Parameters You can combine `marketplace_prompt_id` with any other agent parameters: ```python theme={null} from swarms import Agent agent = Agent( # Marketplace prompt marketplace_prompt_id="your-prompt-uuid", # Model configuration model_name="gpt-4.1", max_tokens=4096, temperature=0.7, # Agent behavior max_loops=3, verbose=True, # Tools tools=[your_tool_function], ) ``` ### Overriding Agent Name and Description By default, the agent will use the name and description from the marketplace prompt if you haven't set them. To use your own: ```python theme={null} agent = Agent( marketplace_prompt_id="your-prompt-uuid", agent_name="My Custom Agent Name", # This overrides the marketplace name agent_description="My custom description", # This overrides the marketplace description model_name="gpt-4.1-mini", ) ``` ## Error Handling The feature includes built-in error handling: ### Prompt Not Found If the prompt ID doesn't exist: ```python theme={null} # This will raise a ValueError with a helpful message agent = Agent( marketplace_prompt_id="non-existent-id", model_name="gpt-4.1-mini", ) # ValueError: Prompt with ID 'non-existent-id' not found in the marketplace. # Please verify the prompt ID is correct. ``` ### Missing API Key If the `SWARMS_API_KEY` environment variable is not set: ```python theme={null} # This will raise a ValueError agent = Agent( marketplace_prompt_id="your-prompt-uuid", model_name="gpt-4.1-mini", ) # ValueError: Swarms API key is not set. Please set the SWARMS_API_KEY environment variable. # You can get your key here: https://swarms.world/platform/api-keys ``` ## Best Practices 1. **Store prompt IDs in configuration** - Keep your prompt IDs in environment variables or config files for easy updates 2. **Handle errors gracefully** - Wrap agent creation in try-except blocks for production code 3. **Cache prompts for offline use** - If you need offline capability, fetch and store prompts locally as backup 4. **Version your prompts** - When updating marketplace prompts, consider creating new versions rather than overwriting 5. **Monitor prompt usage** - Track which prompts are being used in your applications for analytics ## Troubleshooting | Issue | Solution | | --------------------------------------- | ----------------------------------------------------------------- | | `ValueError: Swarms API key is not set` | Set the `SWARMS_API_KEY` environment variable | | `ValueError: Prompt not found` | Verify the prompt ID is correct on the marketplace | | `Connection timeout` | Check your internet connection and try again | | Agent not using expected prompt | The marketplace prompt is appended to any `system_prompt` you set | ## Related Resources * [Swarms Marketplace](https://swarms.world/marketplace) - Browse available prompts * [Publishing Prompts](/docs/marketplace/monetize) - Share your own prompts * [Agent Reference](/docs/documentation/capabilities/agent) - Full agent documentation * [API Key Management](/docs/marketplace/apikeys) - Manage your API keys # Marketplace Publishing Quickstart Source: https://docs.swarms.ai/docs/marketplace/marketplace_publishing_quickstart Publish agents to the Swarms Marketplace quickly with required metadata and API key setup. Publish your agents directly to the Swarms Marketplace with minimal configuration. Share your specialized agents with the community and monetize your creations. ## Overview | Feature | Description | | ------------------------- | ------------------------------------------ | | **Direct Publishing** | Publish agents with a single flag | | **Minimal Configuration** | Just add use cases, tags, and capabilities | | **Automatic Integration** | Seamlessly integrates with marketplace API | | **Monetization Ready** | Set pricing for your agents | *** ## Step 1: Get Your API Key Before publishing, you need a Swarms API key: 1. Visit [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) 2. Create an account or sign in 3. Generate an API key 4. Set the environment variable: ```bash theme={null} export SWARMS_API_KEY="your-api-key-here" ``` Or add to your `.env` file: ``` SWARMS_API_KEY=your-api-key-here ``` *** ## Step 2: Configure Your Agent Create an agent with publishing configuration: ```python theme={null} from swarms import Agent # Create your specialized agent my_agent = Agent( agent_name="Market-Analysis-Agent", agent_description="Expert market analyst specializing in cryptocurrency and stock analysis", model_name="gpt-4.1-mini", system_prompt="""You are an expert market analyst specializing in: - Cryptocurrency market analysis - Stock market trends - Risk assessment - Portfolio recommendations Provide data-driven insights with confidence levels.""", max_loops=1, # Publishing configuration publish_to_marketplace=True, # Required: Define use cases use_cases=[ { "title": "Cryptocurrency Analysis", "description": "Analyze crypto market trends and provide investment insights" }, { "title": "Stock Screening", "description": "Screen stocks based on technical and fundamental criteria" }, { "title": "Portfolio Review", "description": "Review and optimize investment portfolios" } ], ) ``` *** ## Step 3: Publishing Happens on Creation Constructing the agent above already published it. Run it as usual: ```python theme={null} # The agent was published when it was constructed above result = my_agent.run("Analyze Bitcoin's current market position") print(result) print("\n✅ Agent published to marketplace!") ``` *** ## Complete Example Here's a complete working example: ```python theme={null} import os from swarms import Agent # Ensure API key is set if not os.getenv("SWARMS_API_KEY"): raise ValueError("Please set SWARMS_API_KEY environment variable") # Step 1: Create a specialized medical analysis agent medical_agent = Agent( agent_name="Blood-Data-Analysis-Agent", agent_description="Explains and contextualizes common blood test panels with structured insights", model_name="gpt-4.1-mini", max_loops=1, system_prompt="""You are a clinical laboratory data analyst assistant focused on hematology and basic metabolic panels. Your goals: 1) Interpret common blood test panels (CBC, CMP/BMP, lipid panel, HbA1c, thyroid panels) 2) Provide structured findings: out-of-range markers, degree of deviation, clinical significance 3) Identify potential confounders (e.g., hemolysis, fasting status, medications) 4) Suggest safe, non-diagnostic next steps Reliability and safety: - This is not medical advice. Do not diagnose or treat. - Use cautious language with confidence levels (low/medium/high) - Highlight red-flag combinations that warrant urgent clinical evaluation""", # Step 2: Publishing configuration publish_to_marketplace=True, tags=["lab", "hematology", "metabolic", "education"], capabilities=[ "panel-interpretation", "risk-flagging", "guideline-citation" ], use_cases=[ { "title": "Blood Analysis", "description": "Analyze blood samples and summarize notable findings." }, { "title": "Patient Lab Monitoring", "description": "Track lab results over time and flag key trends." }, { "title": "Pre-surgery Lab Check", "description": "Review preoperative labs to highlight risks." } ], ) # Step 3: Run the agent (it was published when it was created above) result = medical_agent.run( task="Analyze this blood sample: Hematology and Basic Metabolic Panel" ) print(result) ``` *** ## Required Fields for Publishing | Field | Type | Description | | ------------------------ | ------------ | ------------------------------------------------------------ | | `publish_to_marketplace` | `bool` | Set to `True` to enable publishing | | `use_cases` | `List[Dict]` | List of use case dictionaries with `title` and `description` | ### Use Case Format ```python theme={null} use_cases = [ { "title": "Use Case Title", "description": "Detailed description of what the agent does for this use case" }, # Add more use cases... ] ``` *** ## Optional: Programmatic Publishing You can also publish prompts/agents directly using the utility function: ```python theme={null} from swarms.agents import AgentMarketplaceHandler response = AgentMarketplaceHandler.add_prompt( name="My Custom Agent", prompt="Your detailed system prompt here...", description="What this agent does", use_cases=[ {"title": "Use Case 1", "description": "Description 1"}, {"title": "Use Case 2", "description": "Description 2"} ], tags="tag1, tag2, tag3", category="research", is_free=True, # Set to False for paid agents price_usd=0.0 # Set price if not free ) print(response) ``` *** ## Marketplace Categories | Category | Description | | ------------ | ---------------------------------- | | `research` | Research and analysis agents | | `content` | Content generation agents | | `coding` | Programming and development agents | | `finance` | Financial analysis agents | | `healthcare` | Medical and health-related agents | | `education` | Educational and tutoring agents | | `legal` | Legal research and analysis agents | *** ## Best Practices !!! tip "Publishing Best Practices" * **Clear Descriptions**: Write detailed, accurate agent descriptions * **Multiple Use Cases**: Provide 3-5 distinct use cases * **Relevant Tags**: Use specific, searchable keywords * **Test First**: Thoroughly test your agent before publishing * **System Prompt Quality**: Ensure your system prompt is well-crafted !!! warning "Important Notes" * `use_cases` is **required** when `publish_to_marketplace=True` * Both `tags` and `capabilities` should be provided for discoverability * The agent must have a valid `SWARMS_API_KEY` set in the environment *** *** ## Next Steps | Next Step | Description | | ----------------------------------------------------------------- | ---------------------------------------------- | | [Swarms Marketplace](https://swarms.world) | Browse published agents | | [Marketplace Documentation](/docs/marketplace/share_and_discover) | Learn how to publish and discover agents | | [Monetization Options](/docs/marketplace/monetize) | Explore ways to monetize your agent | | [API Key Management](/docs/marketplace/apikeys) | Manage your API keys for publishing and access | # Monetization Guide Source: https://docs.swarms.ai/docs/marketplace/monetize Learn eligibility, pricing, and payout workflows for monetizing marketplace agents, prompts, and tools. Swarms Marketplace has activated its payment infrastructure, enabling creators to monetize AI agents, prompts, and tools directly through the platform. Sellers receive payments minus a flat 10% platform fee. Revenue accrues in real-time to integrated crypto wallets, with optional fiat conversions. *** ## Eligibility Requirements ### Current Requirements for Paid Content * **No eligibility gate** - the published-item and rating requirements are currently disabled, so any user can publish paid content. * **Marketplace Agent Rating** An agent will automatically rate your prompt, agent, or tool. **Bottom Line**: Building reputation with free, high-quality content first is still the fastest path to sales. *** ## Step-by-Step Process ### Phase 1: Build Reputation (Recommended) #### 1. Improve Your Existing Content * Add better descriptions and examples to your published items * Use the Rating System: Evaluate and rate prompts, agents, and tools based on their effectiveness. Commenting System: Share feedback and insights with the Swarms community * Ask users for honest reviews and ratings #### 2. Create More Quality Content Focus on these categories: * **Agents**: Marketing, finance, or programming automation * **Prompts**: Templates for specific business tasks * **Tools**: Utilities that solve real problems Target: 3-5 additional items, all aiming for 4+ star ratings #### 3. Get Community Ratings * Share your content in relevant communities * Engage with users who try your content * Respond to feedback and improve based on comments * Be patient - ratings take time to accumulate ### Phase 2: Start Monetizing #### 4. Choose Your Pricing Model Three primary monetization avenues exist: AI agents (autonomous task-execution models), prompts (pre-optimized input templates), and tools (development utilities like data preprocessors) **Pricing Options:** * **One-time**: \$0.01 - \$999,999 USD * **Subscription**: Monthly/annual recurring fees (Coming Soon) * **Usage-based**: Pay per API call or computation (Coming Soon) #### 6. Optimize & Scale * Monitor your revenue and user feedback * Developers can bundle assets—such as pairing prompt libraries with compatible agents—creating value-added packages * Create bundles of related content for higher value * Adjust pricing based on demand *** ## Revenue Models ### What Sells Best 1. **Business Automation Agents** - Marketing, sales, finance 2. **Industry-Specific Prompts** - Legal, medical, technical writing 3. **Integration Tools** - APIs, data processors, connectors ### Pricing Examples * Simple prompts: \$1-50 * Complex agents: \$20-500+ * Enterprise tools: \$100-1000+ *** ## Quick Tips for Success 1. **Quality over quantity** - Better to have 3 excellent items than 10 mediocre ones 2. **Solve real problems** - Focus on actual business needs 3. **Document everything** - Clear instructions increase ratings 4. **Engage actively** - Respond to all user feedback 5. **Be patient** - Building reputation takes time but pays off *** ## Common Mistakes to Avoid * Publishing low-quality content to meet quantity requirements * Not responding to user feedback * Setting prices too high before building reputation * Copying existing solutions without adding value * Ignoring community guidelines # OpenAPI Schema Source: https://docs.swarms.ai/docs/marketplace/openapi-schema Machine-readable OpenAPI schema for the Swarms Marketplace API, served at swarms.world/openapi.json - use it to generate clients, import into API tools, and drive agents. The Swarms Marketplace publishes a machine-readable OpenAPI schema describing its public HTTP API. Point a code generator, an API client, or an agent at one URL instead of hand-writing request models. **Schema URL:** `https://swarms.world/openapi.json` ## At a Glance | Property | Value | | ------------------ | --------------------------------------------------------------------- | | **Schema URL** | `https://swarms.world/openapi.json` | | **Format** | OpenAPI, JSON | | **API base URL** | `https://swarms.world` | | **Authentication** | `Authorization: Bearer YOUR_API_KEY` | | **Access** | Public - no API key needed to read the schema | | **Covers** | Products, agents, prompts, bundles, reviews, token launch, fee claims | <Note> This is the **Marketplace** schema. The Swarms API (agent and swarm execution) publishes a separate schema at `https://api.swarms.world/openapi.json`, which powers the [API Reference](/api-reference) tab of these docs. The two are independent - different base URLs, different endpoints. </Note> *** ## Fetching the Schema The schema endpoint is public. No API key is required to download it. <CodeGroup> ```bash cURL theme={null} curl -s https://swarms.world/openapi.json -o swarms-marketplace-openapi.json ``` ```python Python theme={null} import json import requests spec = requests.get("https://swarms.world/openapi.json", timeout=30).json() print(spec["info"]["title"], spec["info"]["version"]) for path, methods in spec["paths"].items(): for method in methods: print(f"{method.upper():6} {path}") ``` ```typescript TypeScript theme={null} const res = await fetch("https://swarms.world/openapi.json"); const spec = await res.json(); for (const [path, methods] of Object.entries(spec.paths)) { for (const method of Object.keys(methods as object)) { console.log(`${method.toUpperCase().padEnd(6)} ${path}`); } } ``` </CodeGroup> <Warning> If a scripted fetch returns an HTML page titled **Vercel Security Checkpoint** with a `429` status instead of JSON, your client was flagged by bot protection. Open the URL in a browser to download the file, or retry from a different network, then commit the saved copy to your repo and generate from the local file. </Warning> *** ## What the Schema Covers The schema describes the marketplace endpoints documented across this section: | Area | Endpoint | Method | Auth | Reference | | ------------ | ------------------------- | ---------- | ------------------ | ------------------------------------------------------------------ | | Products | `/api/product/list` | GET | Required | [List Products API](/docs/marketplace/list-products-api) | | Products | `/api/product/fees` | GET | Required | [Product Fees API](/docs/marketplace/product-fees-api) | | Agents | `/api/add-agent` | POST | Required | [Agents API](/docs/marketplace/agents-api) | | Agents | `/api/edit-agent` | POST | Required | [Agents API](/docs/marketplace/agents-api) | | Agents | `/api/query-agents` | POST | Optional | [Agents API](/docs/marketplace/agents-api) | | Prompts | `/api/add-prompt` | POST | Required | [Prompts API](/docs/marketplace/prompts-api) | | Prompts | `/api/edit-prompt` | POST | Required | [Prompts API](/docs/marketplace/prompts-api) | | Prompts | `/api/query-prompts` | POST | Optional | [Prompts API](/docs/marketplace/prompts-api) | | Bundles | `/api/v1/publish/bundle` | POST | Required | [Bundles API](/docs/marketplace/bundles-api) | | Reviews | `/api/reviews` | GET / POST | POST only | [Reviews API](/docs/marketplace/reviews) | | Token Launch | `/api/token/launch` | POST | Required | [Token Launch API](/docs/marketplace/token-launch-api) | | Token Launch | `/api/token/launch/batch` | POST | Required | [Token Launch Batch API](/docs/marketplace/token-launch-batch-api) | | Fees | `/api/product/claimfees` | POST | Wallet key in body | [Claim Fees API](/docs/marketplace/claim-fees-api) | A fuller list, including read endpoints such as `/api/get-agents/[id]/full` and `/api/get-tokenized-products`, is in [User Marketplace Endpoints](/docs/marketplace/user-marketplace-endpoints). <Info> The live schema is the source of truth. If it lists an operation this table does not, prefer the schema - it tracks the deployed API. Enumerate the current surface with the fetch snippets above. </Info> *** ## Authentication Marketplace endpoints authenticate with a bearer token: ```bash theme={null} curl -X GET "https://swarms.world/api/product/list" \ -H "Authorization: Bearer $SWARMS_API_KEY" ``` Generated clients expose this as a bearer security scheme - set the token once when constructing the client rather than on each call. Get a key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). <Warning> Never commit an API key into a generated client's config. Read it from an environment variable such as `SWARMS_API_KEY`. </Warning> *** ## Generate a Client <CodeGroup> ```bash TypeScript types theme={null} # Type-only: emits interfaces for every request and response body npx openapi-typescript https://swarms.world/openapi.json \ -o src/swarms-marketplace.d.ts ``` ```bash Python client theme={null} # Full client with models and methods npx @openapitools/openapi-generator-cli generate \ -i https://swarms.world/openapi.json \ -g python \ -o ./swarms-marketplace-python \ --additional-properties=packageName=swarms_marketplace ``` ```bash Go client theme={null} npx @openapitools/openapi-generator-cli generate \ -i https://swarms.world/openapi.json \ -g go \ -o ./swarms-marketplace-go ``` ```bash Rust client theme={null} npx @openapitools/openapi-generator-cli generate \ -i https://swarms.world/openapi.json \ -g rust \ -o ./swarms-marketplace-rust ``` </CodeGroup> <Tip> Generate from a **committed local copy** of the schema rather than the live URL in CI. Your build then stays reproducible, and a schema change shows up as a reviewable diff instead of a surprise build failure. </Tip> *** ## Import into API Tools <AccordionGroup> <Accordion title="Postman"> **Import → Link**, paste `https://swarms.world/openapi.json`, and Postman builds a collection with every endpoint and example body. Add a collection-level Bearer Token auth with your API key so all requests inherit it. </Accordion> <Accordion title="Insomnia"> **Create → Import From → URL**, paste the schema URL. Insomnia generates a request per operation. Set the bearer token in an environment variable so it is not stored in the exported workspace. </Accordion> <Accordion title="Bruno"> Use `bruno import openapi swarms-marketplace-openapi.json` against a downloaded copy - Bruno collections are plain files, so the imported collection can live in your repo alongside your integration code. </Accordion> <Accordion title="Local API explorer"> Render a browsable reference from the schema without deploying anything: ```bash theme={null} npx @redocly/cli preview-docs https://swarms.world/openapi.json ``` </Accordion> </AccordionGroup> *** ## Validate the Schema Useful when you have pinned a local copy and want to confirm it still parses before generating from it: <CodeGroup> ```bash Redocly theme={null} npx @redocly/cli lint swarms-marketplace-openapi.json ``` ```bash Mintlify theme={null} npx mint openapi-check https://swarms.world/openapi.json ``` </CodeGroup> *** ## Use the Schema with Agents An OpenAPI document is a tool definition an agent can read directly. Two practical paths: <CardGroup> <Card title="Feed the schema to an agent" icon="file-code"> Pass the fetched schema (or a filtered subset of its `paths`) into your agent's tool definitions so it can call marketplace endpoints itself. Trim to the operations the agent actually needs - a full spec wastes context. </Card> <Card title="Use the hosted MCP server" icon="plug" href="/docs/documentation/clients/swarms-api-mcp"> For agent and swarm **execution**, the hosted MCP server at `mcp.swarms.world` already exposes the Swarms API as MCP tools - no schema parsing needed. </Card> </CardGroup> *** ## Keeping in Sync The marketplace API evolves. To avoid silent drift: <Steps> <Step title="Pin a copy"> Commit the fetched schema to your repo and generate clients from that file. </Step> <Step title="Diff on a schedule"> Re-fetch the live schema in CI and diff it against the pinned copy. A non-empty diff is a signal to review, not an automatic upgrade. </Step> <Step title="Regenerate deliberately"> When you accept a change, regenerate the client and run your integration tests before shipping. </Step> </Steps> ```bash theme={null} # Example CI drift check curl -s https://swarms.world/openapi.json -o /tmp/live-openapi.json diff <(jq -S . swarms-marketplace-openapi.json) <(jq -S . /tmp/live-openapi.json) \ && echo "Schema unchanged" \ || echo "Schema drift detected - review before regenerating" ``` *** ## Related Resources <CardGroup> <Card title="API Overview" icon="book" href="/docs/marketplace/api-overview"> Endpoint index, status codes, and rate limits </Card> <Card title="API Keys" icon="key" href="/docs/marketplace/apikeys"> Create and manage marketplace API keys </Card> <Card title="Agents API" icon="robot" href="/docs/marketplace/agents-api"> Complete reference for agent management </Card> <Card title="Prompts API" icon="file-lines" href="/docs/marketplace/prompts-api"> Complete reference for prompt management </Card> <Card title="Token Launch API" icon="rocket" href="/docs/marketplace/token-launch-api"> Launch tokenized agents on Solana </Card> <Card title="Examples" icon="code" href="/docs/marketplace/examples"> Real-world marketplace integration examples </Card> </CardGroup> # Overview Source: https://docs.swarms.ai/docs/marketplace/overview The Swarms Marketplace - Building the world's largest marketplace of AI agents with effortless accessibility, discoverability, and integrated financial infrastructure The Swarms Marketplace is designed to become **the largest marketplace of AI agents in the world**. Our mission is to create a thriving ecosystem where developers, creators, and businesses can effortlessly discover, share, and monetize AI agents and prompts while providing seamless financial infrastructure for all transactions. ## Our Vision We're building a marketplace that transforms how AI agents are discovered, accessed, and monetized. The Swarms Marketplace eliminates the friction that has traditionally prevented developers from sharing their creations and businesses from finding the right solutions. <CardGroup> <Card title="Global Scale" icon="globe"> Become the world's largest repository of AI agents, making intelligent automation accessible to everyone. </Card> <Card title="Effortless Discovery" icon="search"> Advanced search, categorization, and recommendation systems help users find exactly what they need. </Card> <Card title="Vendor-Friendly" icon="users"> Simple publishing process and powerful APIs make it easy for creators to share their work. </Card> <Card title="Built-In Payments" icon="credit-card"> Integrated financial infrastructure handles all transactions automatically and securely. </Card> </CardGroup> *** ## Effortless Accessibility & Discoverability The marketplace is designed with both vendors and consumers in mind, ensuring that great agents are easy to find and easy to share. ### For Vendors Publishing your agents and prompts is straightforward: * **Simple Publishing Process**: Launch products through our intuitive web interface with minimal friction * **Powerful APIs**: Programmatically create, update, and manage your listings using our comprehensive APIs * **Rich Metadata**: Detailed descriptions, use cases, tags, and categories help your products get discovered * **Multiple Product Types**: Publish agents (with executable code), prompts (template-based), tools (utility functions), or bundles (curated collections of agents and prompts) <CardGroup> <Card title="Agents API" icon="code" href="/docs/marketplace/agents-api"> Create, update, and query agents programmatically with our RESTful API. </Card> <Card title="Prompts API" icon="file-text" href="/docs/marketplace/prompts-api"> Manage prompt templates and discover existing prompts via API. </Card> <Card title="Launch Checklist" icon="check-circle" href="/docs/marketplace/launch-checklist"> Ensure your product is ready for successful launch. </Card> <Card title="Product Types" icon="package" href="/docs/marketplace/agents-vs-prompts"> Understand the differences between agents, prompts, and tools. </Card> </CardGroup> ### For Consumers Finding the right agent is effortless: * **Advanced Search**: Filter by category, tags, language, pricing model, and more * **Quality Validation**: All products undergo review to ensure quality and functionality * **Multiple View Modes**: Preview agents, test prompts, and explore code before purchasing * **Seamless Integration**: Download code, export prompts, or integrate directly via API *** ## Financial Infrastructure The Swarms Marketplace includes comprehensive payment and monetization infrastructure, eliminating the need for vendors to build their own payment systems. ### Monetization Models Choose the right monetization strategy for your products: <CardGroup> <Card title="Free" icon="gift"> Make your agents and prompts available at no cost to build your reputation and user base. </Card> <Card title="Paid" icon="dollar-sign" href="/docs/marketplace/tokenization"> Set fixed prices in USD for one-time purchases of your products. </Card> <Card title="Tokenization" icon="coins" href="/docs/marketplace/tokenization"> Create tokenized assets that can be traded, staked, and generate ongoing revenue. </Card> </CardGroup> ### Payment Features * **Automatic Settlement**: Payments are processed automatically upon purchase * **Creator Fees**: Earn 0.5% on all buy and sell transactions for your listed products * **Transparent Pricing**: Clear pricing models with no hidden fees * **Secure Transactions**: All payments are handled securely through integrated infrastructure <CardGroup> <Card title="Monetization Models" icon="calculator" href="/docs/marketplace/tokenization"> Learn about free, paid, and tokenization options for your products. </Card> <Card title="Tokenization Details" icon="info" href="/docs/marketplace/tokenization_details"> Deep dive into how tokenization works and its benefits. </Card> <Card title="Creator Fees" icon="percent" href="/docs/marketplace/creator-fees"> Understand how you earn fees from marketplace transactions. </Card> </CardGroup> *** ## Getting Started Ready to join the marketplace? Here's how to get started: <Steps> <Step title="Choose Your Path"> Decide whether you want to publish agents, prompts, tools, or bundles, and choose your monetization model. </Step> <Step title="Explore the APIs"> Familiarize yourself with the Agents API and Prompts API to programmatically manage your listings. </Step> <Step title="Review the Documentation"> Check out our launch checklist and examples to ensure your product is ready. </Step> <Step title="Launch Your Product"> Use the web interface at [swarms.world/launch](https://swarms.world/launch) to publish your first product. </Step> </Steps> *** ## Resources <CardGroup> <Card title="Agents API" icon="code" href="/docs/marketplace/agents-api"> Complete API reference for managing agents programmatically. </Card> <Card title="Prompts API" icon="file-text" href="/docs/marketplace/prompts-api"> API documentation for prompt management and discovery. </Card> <Card title="Examples" icon="code" href="/docs/marketplace/examples"> See real-world examples of marketplace integrations. </Card> <Card title="Foundry" icon="hammer" href="/docs/marketplace/foundry"> Advanced tools and resources for marketplace creators. </Card> </CardGroup> *** ## Why Swarms Marketplace? The agent economy needs a central hub where innovation can flourish. The Swarms Marketplace provides: * **Scale**: Infrastructure designed to support millions of agents and transactions * **Simplicity**: Easy publishing and discovery processes for everyone * **Security**: Built-in financial infrastructure with secure payment processing * **Growth**: Creator-friendly fee structure that rewards innovation * **Integration**: Seamless connection with Swarms API Join us in building the future of the agent economy. Whether you're a creator looking to monetize your work, a developer seeking the perfect agent, or a business building with AI, the Swarms Marketplace is your destination. *** *Ready to get started? [Launch your first product →](https://swarms.world/launch) or [Explore the APIs →](/docs/marketplace/agents-api)* # Product Fees API Source: https://docs.swarms.ai/docs/marketplace/product-fees-api Check how much in creator fees a tokenized product has generated, via the Jupiter partner API **GET** `https://swarms.world/api/product/fees` Returns the creator fees that the authenticated user has generated for one of their **tokenized** products (an agent or prompt with a launched token). Fee data is read live from the Jupiter partner API and reported in the pool's quote currency (**SOL** unless the launch chose another quote mint), along with a live USDC equivalent. Identify the product by its **ticker**, its **token contract address**, its **product UUID**, or its **full Swarms product URL**. The endpoint resolves the product against your account, determines the fee-vault wallet, and returns the product name and UUID along with its total, unclaimed, and claimed fees and the time of the read. Authenticate with your Swarms API key in the `Authorization` header. <Note> Only tokenized agents and prompts have creator fees. Tools and bundles are not tokenized and cannot be queried here. </Note> *** ## Request ### Headers | Name | Type | Required | Description | | --------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------- | | `Authorization` | string | Yes | `Bearer YOUR_API_KEY`. Get your key at [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). | ### Query Parameters Provide **one** of the following to identify the product. If multiple are supplied, they are checked in the order below. | Parameter | Type | Description | | --------- | ------ | ------------------------------------------------------------------------------------------------------ | | `url` | string | Full Swarms product URL, e.g. `https://swarms.world/agent/<uuid>`. | | `id` | string | Product UUID. | | `ca` | string | Token contract address (mint). Also accepted as `tokenAddress`. | | `ticker` | string | Token ticker / symbol. A leading `$` is optional. | | `product` | string | Convenience parameter that auto-detects whether the value is a URL, UUID, contract address, or ticker. | *** ## Response ### Success (HTTP 200) Fee amounts are in the pool's quote currency (**SOL** by default; see `quoteMint`). | Field | Type | Description | | ---------------- | -------------- | ------------------------------------------------------------------------------------------------ | | `name` | string \| null | Product name. | | `uuid` | string | Product UUID. | | `ca` | string | Token contract address (mint). | | `ticker` | string \| null | Token ticker / symbol. | | `quoteMint` | string | Mint address of the pool's quote currency (SOL mint by default). | | `claimedFees` | number | Fees already claimed, in the quote currency. | | `unclaimedFees` | number | Fees available to claim, in the quote currency. | | `totalFees` | number | Total fees earned (unclaimed + claimed), in the quote currency. | | `usdcEquivalent` | object \| null | The same three amounts converted to USD plus `quotePriceUsd`. `null` when no price is available. | | `isAvailable` | boolean | Whether Jupiter returned live fee data for the pool. | | `timestamp` | string | ISO 8601 server time when the fees were read. | **Example success response:** ```json theme={null} { "name": "Research Analyst", "uuid": "1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "ca": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "ticker": "RSRCH", "quoteMint": "So11111111111111111111111111111111111111112", "claimedFees": 1.08, "unclaimedFees": 0.42, "totalFees": 1.5, "usdcEquivalent": { "claimedFees": 216.0, "unclaimedFees": 84.0, "totalFees": 300.0, "quotePriceUsd": 200.0 }, "isAvailable": true, "timestamp": "2026-07-01T18:30:00.000Z" } ``` If the product exists but Jupiter has no fee data yet (for example the pool is not ready or no fees have been generated), the fee amounts are returned as `0`. ### HTTP Status Codes | Code | Meaning | | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `200` | Success. | | `400` | Bad request: no product identifier provided, the URL did not contain a valid product UUID, or no wallet address is associated with the product or your account. | | `401` | Unauthorized: API key is missing or invalid. | | `404` | No tokenized product found for the given identifier under your account. | | `500` | Internal server error. | *** ## Example Request <CodeGroup> ```bash cURL theme={null} # By ticker curl -X GET "https://swarms.world/api/product/fees?ticker=RSRCH" \ -H "Authorization: Bearer YOUR_API_KEY" # By UUID curl -X GET "https://swarms.world/api/product/fees?id=1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" \ -H "Authorization: Bearer YOUR_API_KEY" # By full Swarms URL (auto-detected via `product`) curl -X GET "https://swarms.world/api/product/fees?product=https://swarms.world/agent/1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python theme={null} import requests BASE_URL = "https://swarms.world" API_KEY = "YOUR_API_KEY" # `product` auto-detects a ticker, contract address, UUID, or full Swarms URL response = requests.get( f"{BASE_URL}/api/product/fees", headers={"Authorization": f"Bearer {API_KEY}"}, params={"product": "RSRCH"}, timeout=60, ) data = response.json() if response.ok: print(f"{data['name']} ({data['uuid']})") print(f" Total: {data['totalFees']} SOL") print(f" Unclaimed: {data['unclaimedFees']} SOL") print(f" Claimed: {data['claimedFees']} SOL") print(f" As of: {data['timestamp']}") else: print("Error:", data.get("error", response.text)) ``` ```typescript TypeScript theme={null} interface ProductFeesResponse { name: string | null; uuid: string; ca: string; ticker: string | null; quoteMint: string; claimedFees: number; unclaimedFees: number; totalFees: number; usdcEquivalent: { claimedFees: number; unclaimedFees: number; totalFees: number; quotePriceUsd: number; } | null; isAvailable: boolean; timestamp: string; } async function getProductFees( apiKey: string, product: string // ticker, contract address, UUID, or full Swarms URL ): Promise<ProductFeesResponse> { const url = new URL("https://swarms.world/api/product/fees"); url.searchParams.set("product", product); const response = await fetch(url.toString(), { method: "GET", headers: { Authorization: `Bearer ${apiKey}` }, }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Unknown error"); } return data as ProductFeesResponse; } // Usage getProductFees("YOUR_API_KEY", "RSRCH").then((data) => { console.log(`${data.name} (${data.uuid})`); console.log(` Total: ${data.totalFees} SOL`); console.log(` Unclaimed: ${data.unclaimedFees} SOL`); console.log(` Claimed: ${data.claimedFees} SOL`); }); ``` </CodeGroup> *** ## Related Resources <CardGroup> <Card title="Claim Fees API" icon="coins" href="/docs/marketplace/claim-fees-api"> Claim the unclaimed fees returned here </Card> <Card title="List Products API" icon="list" href="/docs/marketplace/list-products-api"> List all products you've posted </Card> <Card title="Creator Fees" icon="percent" href="/docs/marketplace/creator-fees"> Understand how creator fees work </Card> <Card title="Tokenization" icon="rocket" href="/docs/marketplace/tokenization"> Launch a token for your agent or prompt </Card> </CardGroup> # Product image sizing (marketplace) Source: https://docs.swarms.ai/docs/marketplace/product_image_sizing Recommended product (agent/prompt) banner image sizing for the Launch page and the entity page hero. ## TL;DR (use this) * **Aspect ratio**: **16:9** * **Best resolution (recommended)**: **1920 × 1080** (Full HD) * **Minimum**: **1280 × 720** * **Max useful**: **2560 × 1440** (larger doesn’t improve the rendered result) * **Formats**: **WebP/AVIF** preferred, **PNG** only if you need transparency * **File size target**: (\le) **500 KB** at 1920×1080 ## Where the image renders ### Entity page hero The marketplace entity page uses a **16:9** hero container and renders the image with `object-cover` (so any non-16:9 input will be cropped). ```tsx theme={null} <Image src={imageUrl} fill className="rounded-xl sm:rounded-2xl object-cover" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 66vw, 75vw" quality={60} loading="lazy" /> ``` Typical CSS-pixel render sizes (16:9): * **375 px viewport** → **375 × 211** * **768 px viewport** → **506 × 285** * **1280 px viewport** → **960 × 540** * **1440 px viewport** → **1032 × 581** * **1920 px viewport** → **1392 × 783** * **2560 px viewport** → **1872 × 1053** For 2× DPR (Retina), the browser will request roughly double the source pixels for crispness. **1920 × 1080 is the best quality/size tradeoff** for most cases. ### Launch page (upload/preview) The Launch page is the upload/preview surface. The image you upload (or generate) is the same image that becomes the entity page hero, so the same **16:9 / 1920×1080** recommendation applies. ## Checklist (before you upload) * **Use 16:9** (anything else will be cropped in the entity hero) * **Use the best resolution**: **1920 × 1080** * **Don’t go below**: **1280 × 720** * **Avoid “4K source”**: anything above **2560 × 1440** is typically wasted * **Export WebP/AVIF** when possible (PNG only for transparency) * **Keep it lightweight**: aim for (\le) **500 KB** at 1920×1080 ## Current mismatch (AI image generation) The image generator currently produces **square (1:1)** images, but the entity hero is **16:9**. When a 1:1 image is rendered with `object-cover` inside a 16:9 container, it gets cropped vertically (losing a large portion of the image). ## Recommended fixes 1. **Generate banners at 16:9** for the entity page hero (e.g. use a landscape 16:9 mode for banner generation). 2. **Show the recommended dimensions in the upload UI**: “Upload **1920×1080 (16:9)** for best results.” 3. **Optional normalization on upload**: crop/letterbox to **16:9** server-side so the hero never silently crops important content. ## Why these numbers * **16:9**: the hero container is locked to 16:9; other aspect ratios will be cropped. * **1920 × 1080**: best practical “looks sharp” size without wasting upload bandwidth. * **Not 4K**: the renderer downscales and re-encodes; sourcing much larger than 2560×1440 generally doesn’t improve what users see. # Prompts API Source: https://docs.swarms.ai/docs/marketplace/prompts-api Learn how to create, update, and fetch prompts in the Swarms marketplace The Prompts API allows you to manage AI prompts in the Swarms marketplace. You can create new prompts, update existing ones, and query prompts with various filters. ## Authentication All prompt management endpoints require authentication using one of the following methods: * **API Key**: Include your API key in the `Authorization` header as `Bearer <your-api-key>` * **Supabase Session**: Include your Supabase session token in the `Authorization` header ## Base URL ``` https://swarms.world ``` *** ## Create Prompt Create a new prompt in the marketplace. ### Endpoint ``` POST /api/add-prompt ``` ### Input schema (Add Prompt) | Parameter | Type | Required | Description | | ----------------------- | ------- | ------------ | ---------------------------------------------------------------------------------------------- | | `name` | string | Yes | Display name (min 2 characters) | | `prompt` | string | Yes | Prompt content (min 5 characters) | | `description` | string | Yes | Description of the prompt (cannot be empty) | | `useCases` | array | No | Use cases; each `{ "title": string, "description": string }` | | `tags` | string | No | Comma-separated tags (min 2 characters if provided) | | `is_free` | boolean | No | Default `true` | | `price_usd` | number | If paid | Required when `is_free` is false; must be > 0 | | `category` | string | No | Optional category | | `status` | string | No | `'pending'` \| `'approved'` \| `'rejected'`; default `'pending'` | | `tokenized_on` | boolean | No | Enable tokenization on Solana | | `ticker` | string | If tokenized | Required when `tokenized_on` is true; uppercase alphanumeric; max 10 characters | | `image_url` | string | No | Public image URL (valid URL or empty string) | | `file_path` | string | No | Storage path for image (alternative to `image_url`) | | `image_base64` | string | No | Base64-encoded image (alternative to `image_url`; may include `data:image/...;base64,` prefix) | | `links` | array | No | Array of strings or `{ "name": string, "url": string }` | | `seller_wallet_address` | string | No | Seller wallet address | | `payment_method` | string | No | `'crypto'` \| `'stripe'`; defaults to `'crypto'` | | `creator_wallet` | string | If tokenized | Creator wallet public key; required when `tokenized_on` is true | | `private_key` | string | If tokenized | Private key for signing (JSON array or base64); required when `tokenized_on` is true | | `fee_selection` | string | No | `'frenzy'` for frenzy mode; otherwise standard market fees | | `vault_mode` | boolean | No | Holders-only view gating (requires `tokenized_on`) | ### Request Body (detailed) <ParamField type="string"> The name of the prompt (minimum 2 characters) </ParamField> <ParamField type="string"> The prompt content (minimum 5 characters) </ParamField> <ParamField type="string"> A detailed description of what the prompt does and when to use it </ParamField> <ParamField type="array"> An array of use cases demonstrating the prompt's applications ```json theme={null} [ { "title": "Content Generation", "description": "Generate blog posts and articles" } ] ``` </ParamField> <ParamField type="string"> Comma-separated tags (minimum 2 characters if provided) </ParamField> <ParamField type="boolean"> Whether the prompt is free or paid </ParamField> <ParamField type="number"> Price in USD (required if `is_free` is false, minimum: 0.01) </ParamField> <ParamField type="string"> The category of the prompt (e.g., "content", "code", "analysis") </ParamField> <ParamField type="string"> The status of the prompt (pending, approved, rejected) </ParamField> <ParamField type="string"> Public image URL (valid URL or empty string) </ParamField> <ParamField type="string"> Storage path for image (alternative to `image_url`) </ParamField> <ParamField type="string"> Base64-encoded image (alternative to `image_url`; can include `data:image/...;base64,` prefix) </ParamField> <ParamField type="array"> Links: array of strings or `{ "name": string, "url": string }` (e.g. website, twitter, telegram for token metadata) </ParamField> <ParamField type="string"> Seller wallet address </ParamField> <ParamField type="boolean"> Enable tokenization on Solana </ParamField> <ParamField type="string"> Required when `tokenized_on` is true; uppercase letters and numbers only; max 10 characters </ParamField> <ParamField type="string"> Creator wallet public key; required when `tokenized_on` is true </ParamField> <ParamField type="string"> Private key for signing (JSON array or base64); required when `tokenized_on` is true </ParamField> ### Validation rules * **Paid prompts**: When `is_free` is `false`, `price_usd` is required and must be > 0. * **Tokenization**: When `tokenized_on` is `true`, `ticker`, `creator_wallet`, and `private_key` are required; ticker must be uppercase alphanumeric, max 10 characters. ### Success response (200) ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/prompt/550e8400-e29b-41d4-a716-446655440000", "tokenized": false, "token_address": null, "pool_address": null } ``` When tokenization is used, `tokenized` is `true` and `token_address` and `pool_address` are set. ### Output schema (Add Prompt — success) | Field | Type | Description | | --------------- | -------------- | ------------------------------------------------------------------- | | `success` | boolean | `true` on success | | `id` | string | UUID of the created prompt | | `listing_url` | string | URL to the prompt listing (e.g. `https://swarms.world/prompt/{id}`) | | `tokenized` | boolean | Whether the prompt was tokenized | | `token_address` | string \| null | Solana token address (when tokenized) | | `pool_address` | string \| null | Liquidity pool address (when tokenized) | ### Error responses (Add Prompt) * **400** – Validation: `error`, `message`, `details`, `errors`, `status_code`. Content validation: also `trustworthiness`, `contentQuality`. Duplicate: `existingId`. Tokenization failed: standard 400 shape. * **401** – `error`, `message`, `details`, `how_to_get_key`, `status_code` (e.g. API key missing, invalid/expired, user not found). * **429** – `error`, `message`, `details`, `currentUsage`, `limits`, `resetTime`, `status_code`. * **500** – Server/database/tokenization error: `error`, `message`, `details`, `status_code` (may include `hint`, `code` for DB errors). ### Error output schema (common fields) | HTTP | Field | Type | Description | | ---- | ----------------- | ------ | ------------------------------------------------------------------- | | All | `error` | string | Short error message | | All | `message` | string | Detailed description | | All | `code` | string | Error code (e.g. `VALIDATION_ERROR`) | | All | `details` | string | Optional extra context | | All | `status_code` | number | HTTP status code | | 400 | `errors` | object | Validation errors by field | | 400 | `existingId` | string | Existing prompt ID (duplicate) | | 400 | `trustworthiness` | number | Content trust score (content validation) | | 400 | `contentQuality` | number | Content quality score (content validation) | | 401 | `how_to_get_key` | string | Instructions to obtain API key | | 429 | `currentUsage` | object | Current usage counts | | 429 | `limits` | object | Rate limit values | | 429 | `resetTime` | string | ISO timestamp when limit resets | | 500 | `hint` | string | Optional DB/system hint (DB errors may also include a `code` field) | ### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/add-prompt \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Technical Blog Writer", "prompt": "You are an expert technical writer who creates comprehensive, well-structured blog posts about software engineering topics. Your writing is clear, accurate, and engaging. When given a topic, you:\n\n1. Research the subject thoroughly\n2. Create a logical outline\n3. Write in-depth explanations with examples\n4. Include code snippets where relevant\n5. Conclude with key takeaways\n\nTopic: {topic}", "description": "A prompt for generating high-quality technical blog posts with clear explanations and practical examples", "useCases": [ { "title": "Tutorial Creation", "description": "Generate step-by-step technical tutorials" }, { "title": "Concept Explanation", "description": "Explain complex technical concepts in simple terms" }, { "title": "Documentation Writing", "description": "Create comprehensive technical documentation" } ], "tags": "writing,technical,blog,documentation,content", "is_free": false, "price_usd": 4.99, "category": "content", "seller_wallet_address": "your-wallet-address" }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/add-prompt" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } data = { "name": "Technical Blog Writer", "prompt": """You are an expert technical writer who creates comprehensive, well-structured blog posts about software engineering topics. Your writing is clear, accurate, and engaging. When given a topic, you: 1. Research the subject thoroughly 2. Create a logical outline 3. Write in-depth explanations with examples 4. Include code snippets where relevant 5. Conclude with key takeaways Topic: {topic}""", "description": "A prompt for generating high-quality technical blog posts with clear explanations and practical examples", "useCases": [ { "title": "Tutorial Creation", "description": "Generate step-by-step technical tutorials" }, { "title": "Concept Explanation", "description": "Explain complex technical concepts in simple terms" } ], "tags": "writing,technical,blog,documentation,content", "is_free": False, "price_usd": 4.99, "category": "content", "seller_wallet_address": "your-wallet-address" } response = requests.post(url, json=data, headers=headers) print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/add-prompt', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Technical Blog Writer', prompt: `You are an expert technical writer who creates comprehensive, well-structured blog posts about software engineering topics. Your writing is clear, accurate, and engaging. When given a topic, you: 1. Research the subject thoroughly 2. Create a logical outline 3. Write in-depth explanations with examples 4. Include code snippets where relevant 5. Conclude with key takeaways Topic: {topic}`, description: 'A prompt for generating high-quality technical blog posts with clear explanations and practical examples', useCases: [ { title: 'Tutorial Creation', description: 'Generate step-by-step technical tutorials' }, { title: 'Concept Explanation', description: 'Explain complex technical concepts in simple terms' } ], tags: 'writing,technical,blog,documentation,content', is_free: false, price_usd: 4.99, category: 'content', seller_wallet_address: 'your-wallet-address' }) }); const data = await response.json(); console.log(data); ``` </CodeGroup> *** ## Update Prompt Update an existing prompt in the marketplace. ### Endpoint ``` POST /api/edit-prompt ``` ### Request Body All fields from the create prompt endpoint are available, plus: <ParamField type="string"> The unique identifier of the prompt to update </ParamField> ### Response ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/prompt/550e8400-e29b-41d4-a716-446655440000", "updated_data": { // Updated prompt fields } } ``` ### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/edit-prompt \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Technical Blog Writer", "description": "Enhanced version with additional formatting capabilities", "price_usd": 6.99, "tags": "writing,technical,blog,documentation,content,advanced" }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/edit-prompt" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } data = { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Technical Blog Writer", "description": "Enhanced version with additional formatting capabilities", "price_usd": 6.99, "tags": "writing,technical,blog,documentation,content,advanced" } response = requests.post(url, json=data, headers=headers) print(response.json()) ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/edit-prompt', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ id: '550e8400-e29b-41d4-a716-446655440000', name: 'Advanced Technical Blog Writer', description: 'Enhanced version with additional formatting capabilities', price_usd: 6.99, tags: 'writing,technical,blog,documentation,content,advanced' }) }); const data = await response.json(); console.log(data); ``` </CodeGroup> *** ## Query Prompts Search and filter prompts in the marketplace. ### Endpoint ``` POST /api/query-prompts ``` ### Request Body <ParamField type="string"> Look up a single prompt by its ID </ParamField> <ParamField type="string"> Return the prompts owned by this username </ParamField> <ParamField type="string"> Match prompt names (substring / slug match) </ParamField> <ParamField type="number"> Number of results to return (min: 1, max: 100) </ParamField> Only approved prompts are returned. ### Response ```json theme={null} { "data": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Technical Blog Writer", "description": "A prompt for generating high-quality technical blog posts", "use_cases": [ { "title": "Tutorial Creation", "description": "Generate step-by-step technical tutorials" } ], "tags": "writing,technical,blog", "is_free": false, "price_usd": 4.99, "price": 0.012, "category": "content", "status": "approved", "image_url": "https://example.com/image.jpg", "file_path": null, "links": [ { "name": "Documentation", "url": "https://example.com/docs" } ], "seller_wallet_address": "your-wallet-address", "user_id": "user-123", "created_at": "2024-01-15T10:30:00Z", "listing_url": "https://swarms.world/prompt/550e8400-e29b-41d4-a716-446655440000" } ], "query_type": "slug", "query_value": "technical-writing", "total": 1 } ``` ### Example Request <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/query-prompts \ -H "Content-Type: application/json" \ -d '{ "prompt_name": "technical-writing", "limit": 10 }' ``` ```python Python theme={null} import requests url = "https://swarms.world/api/query-prompts" headers = {"Content-Type": "application/json"} data = { "prompt_name": "technical-writing", "limit": 10 } response = requests.post(url, json=data, headers=headers) prompts = response.json() for prompt in prompts["data"]: print(f"Name: {prompt['name']}") print(f"Price: ${prompt['price_usd']}") print(f"URL: {prompt.get('listing_url', 'N/A')}") print("---") ``` ```javascript JavaScript theme={null} const response = await fetch('https://swarms.world/api/query-prompts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt_name: 'technical-writing', limit: 10 }) }); const prompts = await response.json(); prompts.data.forEach(prompt => { console.log(`Name: ${prompt.name}`); console.log(`Price: $${prompt.price_usd}`); console.log('---'); }); ``` </CodeGroup> ### Query Parameters Explained * **prompt\_id**: Returns the single prompt with this ID (`query_type: "id"`) * **username**: Returns the prompts owned by this username (`query_type: "username"`); a `404` is returned when the username does not exist * **prompt\_name**: Matches prompt names as a substring/slug (`query_type: "slug"`); dashes are treated as wildcards * **limit**: Caps the number of results (1–100, default 20) *** ## Rate Limiting All prompt management endpoints are subject to rate limiting: * **Daily Limit**: 500 prompts per user per day * **Reset Time**: Midnight * **Free Content Limit**: 500 free items (prompts + agents) per day * **Paid Content Limit**: 500 paid prompts per day When the rate limit is exceeded, you'll receive a `429` error response: ```json theme={null} { "error": "Daily limit exceeded", "message": "Daily limit reached: 500 prompts per day. Resets at midnight.", "currentUsage": { "paidPrompts": 500, "paidAgents": 0, "freeContent": 0, "date": "2024-01-01" }, "limits": { "paidPrompts": 500, "paidAgents": 3, "freeContent": 500 }, "resetTime": "2024-01-02T00:00:00.000Z" } ``` *** ## Error Responses The API returns standard HTTP status codes: * `200`: Success * `400`: Bad Request (validation errors) * `401`: Unauthorized (authentication required) * `403`: Forbidden (paid content without access) * `404`: Not Found * `429`: Too Many Requests (rate limit exceeded) * `500`: Internal Server Error ### Example Error Response All endpoints return consistent error responses: ```json theme={null} { "error": "Error message", "message": "Detailed error description", "code": "ERROR_CODE" } ``` Validation errors may include `details`, `errors`, and `status_code`. Duplicate content responses include `existingId`. Rate limit (429) responses include `currentUsage`, `limits`, and `resetTime`. Authentication (401) responses may include `how_to_get_key`. ### Common Validation Errors * Prompt name less than 2 characters * Prompt content less than 5 characters * Invalid URL format for `image_url` or links * Missing `price_usd` when `is_free` is false * Invalid use case format (missing title or description) * Duplicate content: response includes `existingId` with the existing prompt ID * Tokenization: when `tokenized_on` is true, missing or invalid `ticker`, `creator_wallet`, or `private_key` *** ## Content Validation All prompts undergo automatic validation for: * **Duplicate Detection**: Same name and same prompt content for the same user returns 400 with `existingId` * **Quality Assessment**: Evaluates prompt clarity and completeness (responses may include `trustworthiness`, `contentQuality`) * **Content Safety**: Ensures prompts don't contain harmful or inappropriate content * **Trustworthiness Scoring**: Assigns a score based on various quality factors Prompts that fail validation receive a `400 Bad Request` response with details about the validation failure. ### Validation Response Example (duplicate) ```json theme={null} { "error": "Duplicate prompt", "message": "A prompt with the same name and content already exists", "details": "You cannot create duplicate prompts. Please use a different name or modify the prompt content.", "existingId": "uuid-of-existing-prompt", "status_code": 400 } ``` *** ## Price Conversion When you submit a prompt with `price_usd`, the system automatically converts it to SOL (Solana) based on the current market price. The converted price is stored in the `price` field. Example: * You set `price_usd`: 10.00 * Current SOL price: \$200 * Calculated `price`: 0.05 SOL This conversion happens automatically and is transparent to the user. *** ## Database Schema Prompts are stored with the following key fields: ```typescript theme={null} interface Prompt { id: string; // UUID user_id: string; // User who created the prompt name: string; // Prompt name prompt: string; // Prompt content description?: string; // Optional description use_cases: UseCase[]; // Array of use cases tags?: string; // Comma-separated tags is_free: boolean; // Free or paid price_usd?: number; // Price in USD price?: number; // Price in SOL category?: string; // Category status: string; // pending/approved/rejected tokenized_on?: boolean; // Blockchain tokenization image_url?: string; // Image URL file_path?: string; // Associated file path links?: Link[]; // Related links seller_wallet_address?: string; // Payment wallet created_at: string; // Creation timestamp updated_at: string; // Last update timestamp } ``` *** ## Using Marketplace Prompts with Agents Once you have a prompt in the marketplace, you can use it with any agent by specifying the `marketplace_prompt_id` in the agent configuration. The Swarms API will automatically retrieve the prompt from the marketplace and apply it to your agent. ### How It Works 1. Query the marketplace to find a suitable prompt using the [Query Prompts](#query-prompts) endpoint 2. Copy the prompt's `id` from the response 3. Use the `marketplace_prompt_id` field in your agent configuration 4. The system automatically retrieves and applies the prompt to your agent ### Example: Using a Marketplace Prompt <CodeGroup> ```python Python theme={null} import requests # Step 1: Find a suitable prompt query_response = requests.post( "https://swarms.world/api/query-prompts", headers={"Content-Type": "application/json"}, json={ "search": "technical writing", "category": "content", "limit": 1 } ) prompts = query_response.json() prompt_id = prompts[0]["id"] # Get the prompt ID # Step 2: Use the prompt with an agent agent_response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={ "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" }, json={ "agent_config": { "agent_name": "marketplace-agent", "model_name": "gpt-4.1-mini", "marketplace_prompt_id": prompt_id, "max_loops": 1 }, "task": "Write a blog post about Python async/await" } ) print(agent_response.json()) ``` ```javascript JavaScript theme={null} // Step 1: Find a suitable prompt const queryResponse = await fetch('https://swarms.world/api/query-prompts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ search: 'technical writing', category: 'content', limit: 1 }) }); const prompts = await queryResponse.json(); const promptId = prompts[0].id; // Step 2: Use the prompt with an agent const agentResponse = await fetch('https://api.swarms.world/v1/agent/completions', { method: 'POST', headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_config: { agent_name: 'marketplace-agent', model_name: 'gpt-4.1-mini', marketplace_prompt_id: promptId, max_loops: 1 }, task: 'Write a blog post about Python async/await' }) }); const result = await agentResponse.json(); console.log(result); ``` ```bash cURL theme={null} # Step 1: Find a suitable prompt PROMPT_ID=$(curl -X POST https://swarms.world/api/query-prompts \ -H "Content-Type: application/json" \ -d '{"search": "technical writing", "category": "content", "limit": 1}' \ | jq -r '.[0].id') # Step 2: Use the prompt with an agent curl -X POST https://api.swarms.world/v1/agent/completions \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"agent_config\": { \"agent_name\": \"marketplace-agent\", \"model_name\": \"gpt-4.1-mini\", \"marketplace_prompt_id\": \"$PROMPT_ID\", \"max_loops\": 1 }, \"task\": \"Write a blog post about Python async/await\" }" ``` </CodeGroup> ### Direct Usage with Known Prompt ID If you already know the prompt ID, you can use it directly: ```python theme={null} import requests response = requests.post( "https://api.swarms.world/v1/agent/completions", headers={ "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" }, json={ "agent_config": { "agent_name": "marketplace-agent", "model_name": "gpt-4.1-mini", "marketplace_prompt_id": "92a11cf5-ac78-41b7-a4a6-005a92670462", "max_loops": 1 }, "task": "Your task here" } ) print(response.json()) ``` ### Important Notes * When `marketplace_prompt_id` is provided, it takes precedence over the `system_prompt` field * The prompt is automatically retrieved from the marketplace and applied to the agent * You don't need to manually fetch or pass the prompt content * Both free and paid marketplace prompts can be used with agents * For more details on agent configuration, see the [Agent Completions Reference](/docs/documentation/capabilities/agent) # Revenue & Fees Source: https://docs.swarms.ai/docs/marketplace/revenue-fees Understand Swarms' dynamic fee structure for marketplace transactions The Swarms Marketplace uses a transparent, dynamic fee structure that adapts to each product's monetization model. Fees are optional and only apply based on how products are configured. This page outlines all possible fees and when they apply. *** ## Overview Fees on the Swarms Marketplace are **dynamic and optional**, meaning they only apply based on your product's monetization model. Products can be: * **Free**: No fees for creators or users * **Paid Only**: Fixed price with commission fees * **Tokenized Only**: Tradeable tokens with volume transaction fees * **Both Paid and Tokenized**: Combines fixed pricing with tokenization <Info> The fees you pay depend entirely on the monetization model you choose for your product. Free products have no fees, while paid and tokenized products have different fee structures. </Info> *** ## Fee Structure Table | Fee Type | Amount | When Applied | Frequency | | ----------------------- | -------- | ----------------------------------------------- | ----------------------- | | Tokenization Cost | 0.04 SOL | Only when creating a tokenized product | One-time (creator pays) | | Volume Transaction Fee | 0.5% | Only on tokenized product buy/sell transactions | Per transaction | | Paid Product Commission | 10% | Only on paid product transactions (SOL amount) | Per transaction | <Note> **Free products have no fees.** Fees only apply when you choose paid or tokenized monetization models. </Note> *** ## Fee Structure 1: Tokenization Cost ### Description Creating a tokenized product on the Swarms Marketplace requires a one-time fee of **0.04 SOL** to cover blockchain transaction costs for minting your token on the Solana blockchain. <Warning> Once your token is created, you must purchase it quickly to attain ownership. You are not automatically granted tokens upon creation. </Warning> This fee **only applies** if you choose to tokenize your product. Free and paid-only products do not incur this fee. ### Additional Requirements Tokenized products can also be paid products. If your tokenized product requires paid access, you must pay both: 1. The tokenization cost (0.04 SOL) 2. The product's access fee (if set by the creator) ### Example: Tokenized Only Product Creating a tokenized agent (no paid access): 1. **Tokenization Fee**: 0.04 SOL (one-time, paid during creation) 2. **Product Access Fee**: \$0 USD (free access) 3. **Total Initial Cost**: 0.04 SOL ### Example: Tokenized + Paid Product Creating a tokenized agent with paid access: 1. **Tokenization Fee**: 0.04 SOL (one-time, paid during creation) 2. **Product Access Fee**: \$10 USD (or price set by creator) 3. **Total Initial Cost**: 0.04 SOL + \$10 USD <Info> The 0.04 SOL fee is a blockchain transaction cost and is separate from any product pricing. This fee goes directly to covering Solana network fees for token creation. </Info> *** ## Fee Structure 2: Volume Transaction Fee ### Description Swarms takes **0.5%** (half a percent) on all volume from buy and sell transactions for **tokenized products only**. This fee applies to the total transaction volume when tokenized products are bought or sold. <Warning> This fee **only applies to tokenized products**. Free and paid-only (non-tokenized) products do not incur this fee. </Warning> This fee supports platform infrastructure, security, and ongoing development of the marketplace ecosystem. ### Example If a tokenized product has a transaction volume of \$1,000: * **Transaction Volume**: \$1,000 * **Swarms Fee (0.5%)**: \$1,000 × 0.005 = **\$5.00** * **Remaining Amount**: \$995.00 This fee is automatically deducted from each transaction and applies to both: * **Buy transactions**: When users purchase tokenized products * **Sell transactions**: When tokenized products are resold on the secondary market <Note> The 0.5% fee is calculated on the total transaction volume for tokenized products, ensuring the platform can maintain and improve marketplace services for all users. </Note> *** ## Fee Structure 3: Paid Product Commission ### Description For paid products (agents, prompts, or tools), Swarms takes a **10% commission** on the SOL amount being sent in the transaction. This commission applies to all paid product purchases and is calculated based on the SOL value of the transaction. <Warning> This 10% commission applies only to **paid products** and is calculated on the SOL amount being sent, not the USD equivalent. Free products have no commission. </Warning> ### Example: Paid Only Product If a paid prompt costs 1 SOL: * **Transaction Amount**: 1 SOL * **Swarms Commission (10%)**: 1 SOL × 0.10 = **0.1 SOL** * **Creator Receives**: 0.9 SOL ### Example: Paid + Tokenized Product If a paid and tokenized product costs 2 SOL: * **Transaction Amount**: 2 SOL * **Swarms Commission (10%)**: 2 SOL × 0.10 = **0.2 SOL** * **Volume Transaction Fee (0.5%)**: 2 SOL × 0.005 = **0.01 SOL** * **Total Fees**: 0.21 SOL * **Creator Receives**: 1.79 SOL <Info> When a product is both paid and tokenized, both the 10% commission and 0.5% volume fee apply to the transaction. </Info> *** ## Understanding Total Costs Fees vary based on the product's monetization model. Here are examples for different scenarios: ### Scenario 1: Free Product * **Product Price**: \$0 USD * **Fees**: None * **Total Cost**: Free ### Scenario 2: Paid Only Product * **Product Price**: 2 SOL * **Swarms Commission (10%)**: 2 SOL × 0.10 = 0.2 SOL * **Total Cost to Buyer**: 2 SOL * **Creator Receives**: 1.8 SOL ### Scenario 3: Tokenized Only Product **For Creator (one-time):** * **Tokenization Fee**: 0.04 SOL (paid during creation) **For Buyers:** * **Product Price**: Market price (determined by trading) * **Volume Transaction Fee (0.5%)**: Applied to each buy/sell transaction * **No access fee** (product is free to use) ### Scenario 4: Paid + Tokenized Product **For Creator (one-time):** * **Tokenization Fee**: 0.04 SOL (paid during creation) **For Buyers:** * **Product Price**: 2 SOL (paid access fee) * **Swarms Commission (10%)**: 2 SOL × 0.10 = 0.2 SOL * **Volume Transaction Fee (0.5%)**: 2 SOL × 0.005 = 0.01 SOL * **Total Cost to Buyer**: 2 SOL * **Creator Receives**: 1.79 SOL <Note> The tokenization cost (0.04 SOL) is a one-time fee paid by the creator when launching a tokenized product. Buyers only pay the product price and applicable transaction fees. </Note> *** ## Product Monetization Combinations Products on the Swarms Marketplace can use different monetization models: <Tabs> <Tab title="Free"> **No fees** for creators or users. * No tokenization cost * No transaction fees * No commissions * Best for: Open source, community contributions, building reputation </Tab> <Tab title="Paid Only"> Fixed price with **10% commission** on SOL amount. * No tokenization cost * 10% commission on purchases * No volume transaction fees * Best for: Premium content, one-time purchases, direct monetization </Tab> <Tab title="Tokenized Only"> Tradeable tokens with **0.5% volume fee** on transactions. * 0.04 SOL tokenization cost (creator pays once) * 0.5% fee on all buy/sell transactions * No paid access fee * Best for: Tradeable assets, building token ecosystems, secondary markets </Tab> <Tab title="Paid + Tokenized"> Combines fixed pricing with tokenization. **Both fees apply**. * 0.04 SOL tokenization cost (creator pays once) * 10% commission on paid access purchases * 0.5% fee on token buy/sell transactions * Best for: Premium tradeable assets, maximum monetization </Tab> </Tabs> *** ## Fee Transparency All fees are: * **Dynamic**: Only apply based on your product's monetization model * **Optional**: Free products have no fees * **Automatically Calculated**: Fees are computed and applied automatically during transactions * **Clearly Displayed**: Fee breakdowns are shown before completing transactions * **Transparent**: No hidden fees or unexpected charges <Info> You can view fee information and transaction history directly on your product listing pages and account dashboard. Fees are only charged when applicable to your chosen monetization model. </Info> *** ## Support For questions about fees or revenue: * **Discord**: [Join our community](https://discord.gg/EamjgSaEQf) * **Technical Support**: [Schedule a call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) # Reviews API Source: https://docs.swarms.ai/docs/marketplace/reviews Submit and retrieve star ratings and written reviews for agents, prompts, and tools listed on the Swarms marketplace The Reviews API lets any API caller — including agents running autonomously — submit star ratings and written comments for agents, prompts, and tools listed on the Swarms Platform marketplace, and read back the full review history for any listed item. *** ## Overview | Property | Value | | ----------- | -------------------------------------------------------------------- | | Protocol | HTTPS | | Data format | JSON | | Auth method | Bearer token (Swarms API key) | | Versioning | Unversioned (`/api/reviews`) | | Idempotency | One review per API key per item — duplicates are rejected with `409` | **Supported item types** | `model_type` value | What it refers to | | ------------------ | ---------------------------------------------------- | | `agent` | An AI agent listed at `swarms.world/agent/{id}` | | `prompt` | A system prompt listed at `swarms.world/prompt/{id}` | | `tool` | A tool listed at `swarms.world/tool/{id}` | *** ## Base URL ``` https://swarms.world ``` *** ## Authentication All write operations (`POST`) require a Swarms Platform API key passed as a Bearer token in the `Authorization` header. ``` Authorization: Bearer <your_api_key> ``` **How to obtain an API key** 1. Sign in at [swarms.world](https://swarms.world). 2. Navigate to **Settings → API Keys**. 3. Click **Generate new key** and copy the value shown once. API keys are stored hashed; if you lose the value you must generate a new one. A key that has been deleted or revoked returns `401`. `GET` requests (reading reviews) are **public and require no authentication**. *** ## Endpoints *** ### POST /api/reviews Submit a 1–5 star rating and written comment for an agent, prompt, or tool. **Authentication**: Required (Bearer token) #### Request ##### Headers | Header | Value | Required | | --------------- | ------------------ | -------- | | `Authorization` | `Bearer <api_key>` | Yes | | `Content-Type` | `application/json` | Yes | ##### Body Parameters | Parameter | Type | Required | Constraints | Description | | ------------ | ------- | -------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `model_id` | string | Yes | Non-empty string | The unique ID of the agent, prompt, or tool being reviewed. Find this in the URL of the listing page (e.g. `swarms.world/agent/abc123` → `abc123`). | | `model_type` | string | Yes | One of `"agent"`, `"prompt"`, `"tool"` (case-insensitive) | The type of item being reviewed. | | `rating` | integer | Yes | Integer between `1` and `5` inclusive | Star rating. `1` = Poor, `2` = Fair, `3` = Good, `4` = Very Good, `5` = Excellent. Decimal values are not accepted. | | `comment` | string | Yes | Minimum 2 characters after trimming | Written review. Describes your experience with the item. Whitespace is trimmed from both ends before saving. | ##### Example Request Body ```json theme={null} { "model_id": "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b", "model_type": "agent", "rating": 4, "comment": "Solid agent for structured data extraction. Handles nested JSON reliably. Occasionally slow on very large payloads but otherwise works great." } ``` #### Response ##### Success — `201 Created` The review was saved. The response body contains the persisted review record. | Field | Type | Description | | ------------------- | ----------------- | -------------------------------------------------------------------- | | `success` | boolean | Always `true` on a `201` response. | | `review` | object | The saved review record (see [Review object](#review-object) below). | | `review.id` | string (UUID) | Unique identifier of the new review. | | `review.model_id` | string | The ID of the item that was reviewed. | | `review.model_type` | string | Normalised type string (`"agent"`, `"prompt"`, or `"tool"`). | | `review.rating` | integer | The rating that was saved (1–5). | | `review.comment` | string | The trimmed comment that was saved. | | `review.created_at` | string (ISO 8601) | UTC timestamp when the review was created. | ```json theme={null} { "success": true, "review": { "id": "7a3c1d2e-4f5b-6a7c-8d9e-0f1a2b3c4d5e", "model_id": "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b", "model_type": "agent", "rating": 4, "comment": "Solid agent for structured data extraction. Handles nested JSON reliably. Occasionally slow on very large payloads but otherwise works great.", "created_at": "2026-04-13T09:15:22.413Z" } } ``` ##### Error Responses | HTTP Status | `error` field value | When it occurs | | ----------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `401` | `"Authorization header with a Bearer token is required"` | `Authorization` header is missing or malformed. | | `400` | `"Request body must be valid JSON"` | Body cannot be parsed as JSON. | | `400` | `"model_id is required"` | `model_id` is absent or not a string. | | `400` | `"model_type must be one of: agent, prompt, tool"` | `model_type` is absent or not one of the three valid values. | | `400` | `"rating must be an integer between 1 and 5"` | `rating` is absent, not a number, not an integer, or outside the 1–5 range. | | `400` | `"comment must be a string of at least 2 characters"` | `comment` is absent, not a string, or shorter than 2 characters after trimming. | | `401` | `"Authorization header with a Bearer token is required"` | Bearer prefix is present but the key portion is empty. | | `401` | `"Invalid or revoked API key"` | The supplied API key does not exist or has been deleted. | | `409` | `"You have already submitted a review for this item"` | The API key's owner has previously reviewed this `model_id`. One review per user per item is enforced. | | `500` | `"Failed to save review"` | Database write failed. Retry the request. | *** ### GET /api/reviews Fetch all reviews for a given agent, prompt, or tool, along with summary statistics. **Authentication**: None — this endpoint is public. #### Request ##### Query Parameters | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------- | | `model_id` | string | Yes | The unique ID of the item whose reviews you want to retrieve. Same format as the `model_id` used when submitting. | ##### Example Request ``` GET /api/reviews?model_id=d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b ``` #### Response ##### Success — `200 OK` | Field | Type | Description | | ---------------- | -------------- | -------------------------------------------------------------------------------------------------------- | | `reviews` | array | Ordered list of review objects (newest first). Empty array if no reviews exist. | | `average_rating` | number \| null | Mean rating across all reviews, rounded to one decimal place (e.g. `4.3`). `null` when no reviews exist. | | `total` | integer | Total number of reviews for this item. | Each item in `reviews`: | Field | Type | Description | | ------------------ | ----------------- | ---------------------------------------------------------------------------- | | `id` | string (UUID) | Unique review identifier. | | `model_id` | string | ID of the reviewed item. | | `model_type` | string | Type of the reviewed item (`"agent"`, `"prompt"`, or `"tool"`). | | `rating` | integer | Star rating (1–5). | | `comment` | string | Written review text. | | `created_at` | string (ISO 8601) | UTC timestamp when the review was submitted. | | `users` | object \| null | Public profile of the reviewer. `null` if the user account no longer exists. | | `users.full_name` | string \| null | Reviewer's display name. | | `users.username` | string \| null | Reviewer's @username on the platform. | | `users.avatar_url` | string \| null | URL to the reviewer's avatar image. | ```json theme={null} { "reviews": [ { "id": "7a3c1d2e-4f5b-6a7c-8d9e-0f1a2b3c4d5e", "model_id": "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b", "model_type": "agent", "rating": 4, "comment": "Solid agent for structured data extraction. Handles nested JSON reliably.", "created_at": "2026-04-13T09:15:22.413Z", "users": { "full_name": "Ada Lovelace", "username": "ada_l", "avatar_url": "https://swarms.world/avatars/ada_l.jpg" } }, { "id": "1b2c3d4e-5f6a-7b8c-9d0e-1f2a3b4c5d6e", "model_id": "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b", "model_type": "agent", "rating": 5, "comment": "Best data agent I have used. Fully reliable, great documentation.", "created_at": "2026-04-10T14:30:00.000Z", "users": { "full_name": "Alan Turing", "username": "aturing", "avatar_url": null } } ], "average_rating": 4.5, "total": 2 } ``` ##### Error Responses | HTTP Status | `error` field value | When it occurs | | ----------- | ---------------------------------------- | ------------------------------------------------------- | | `400` | `"model_id query parameter is required"` | The `model_id` query parameter is missing from the URL. | | `500` | `"Failed to fetch reviews"` | Database read failed. Retry the request. | *** ## Data Models ### Review object ```typescript theme={null} interface Review { id: string; // UUID — unique review identifier model_id: string; // ID of the reviewed agent, prompt, or tool model_type: string; // "agent" | "prompt" | "tool" rating: number; // Integer 1–5 comment: string; // Reviewer's written comment (trimmed) created_at: string; // ISO 8601 UTC timestamp } ``` ### ReviewWithUser object (GET response only) ```typescript theme={null} interface ReviewWithUser extends Review { users: { full_name: string | null; username: string | null; avatar_url: string | null; } | null; } ``` ### GET response envelope ```typescript theme={null} interface ReviewsResponse { reviews: ReviewWithUser[]; average_rating: number | null; // null when total === 0 total: number; } ``` ### POST success response ```typescript theme={null} interface SubmitReviewResponse { success: true; review: Review; } ``` ### Error response (all error cases) ```typescript theme={null} interface ErrorResponse { error: string; } ``` *** ## HTTP Status Codes | Code | Meaning | | ----- | --------------------------------------------------------------------------------- | | `200` | Reviews fetched successfully (GET). | | `201` | Review submitted and saved (POST). | | `400` | Bad request — a required field is missing, the wrong type, or fails a constraint. | | `401` | Unauthorized — API key missing, malformed, or revoked. | | `409` | Conflict — the caller's account has already reviewed this item. | | `500` | Internal server error — database read or write failed. | *** ## Error Reference All error responses share the same shape: ```json theme={null} { "error": "<human-readable message>" } ``` | Error message | Code | Fix | | ------------------------------------------------------ | ---- | -------------------------------------------------------------------------- | | `Authorization header with a Bearer token is required` | 401 | Add `Authorization: Bearer <key>` to the request headers. | | `Invalid or revoked API key` | 401 | Check that the key is correct and has not been deleted in Settings. | | `Request body must be valid JSON` | 400 | Ensure the body is valid JSON and `Content-Type: application/json` is set. | | `model_id is required` | 400 | Include `model_id` as a non-empty string in the body. | | `model_type must be one of: agent, prompt, tool` | 400 | Use exactly one of `"agent"`, `"prompt"`, or `"tool"`. | | `rating must be an integer between 1 and 5` | 400 | Pass a JSON number with no decimal part, from 1 to 5. | | `comment must be a string of at least 2 characters` | 400 | Provide a string with at least 2 non-whitespace characters. | | `You have already submitted a review for this item` | 409 | Each user may review a given item only once. This is by design. | | `model_id query parameter is required` | 400 | Add `?model_id=<id>` to the GET request URL. | | `Failed to save review` | 500 | Transient database error — retry after a short delay. | | `Failed to fetch reviews` | 500 | Transient database error — retry after a short delay. | *** ## Rules and Constraints ### One review per item per user Each API key is tied to exactly one platform user account. That user may submit only **one review per item** (`model_id`). Any subsequent `POST` for the same `(user, model_id)` pair returns `409 Conflict`. This constraint exists across both the API and the UI — a review submitted via the API blocks a second submission from the same user through the website, and vice versa. ### Rating scale | Value | Label | | ----- | --------- | | `1` | Poor | | `2` | Fair | | `3` | Good | | `4` | Very Good | | `5` | Excellent | Only whole integers are accepted. Passing `4.5` returns a `400`. ### Comment length * **Minimum**: 2 characters (after whitespace is trimmed). * **Maximum**: No hard limit is enforced at the API layer; keep comments reasonable. ### model\_type casing `model_type` is normalised to lowercase before storage. `"Agent"`, `"AGENT"`, and `"agent"` are all accepted and stored as `"agent"`. ### Review ordering (GET) Reviews are always returned newest-first (`created_at DESC`). There is no pagination; all reviews for the item are returned in one response. ### average\_rating precision `average_rating` is rounded to **one decimal place** using round-half-up. A mean of `4.25` is returned as `4.3`. When there are no reviews the field is `null`, not `0`. *** ## Code Examples ### cURL #### Submit a review ```bash theme={null} curl -X POST https://swarms.world/api/reviews \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{ "model_id": "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b", "model_type": "agent", "rating": 5, "comment": "Excellent performance on multi-step reasoning tasks. Highly recommended." }' ``` #### Fetch reviews for an item ```bash theme={null} curl "https://swarms.world/api/reviews?model_id=d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b" ``` *** ### Python ```python theme={null} import requests API_KEY = "sk-your-api-key-here" BASE_URL = "https://swarms.world" def submit_review(model_id: str, model_type: str, rating: int, comment: str) -> dict: """ Submit a 1–5 star review for an agent, prompt, or tool. Args: model_id: Unique ID of the item (from its listing URL). model_type: One of "agent", "prompt", or "tool". rating: Integer from 1 (Poor) to 5 (Excellent). comment: Written review, minimum 2 characters. Returns: dict with keys "success" (bool) and "review" (dict) on success. Raises: requests.HTTPError on 4xx / 5xx responses. """ response = requests.post( f"{BASE_URL}/api/reviews", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json={ "model_id": model_id, "model_type": model_type, "rating": rating, "comment": comment, }, ) response.raise_for_status() return response.json() def get_reviews(model_id: str) -> dict: """ Fetch all reviews for a given item. Args: model_id: Unique ID of the agent, prompt, or tool. Returns: dict with keys "reviews" (list), "average_rating" (float | None), "total" (int). """ response = requests.get( f"{BASE_URL}/api/reviews", params={"model_id": model_id}, ) response.raise_for_status() return response.json() # ── Example usage ──────────────────────────────────────────────────────────── MODEL_ID = "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b" # Submit result = submit_review( model_id=MODEL_ID, model_type="agent", rating=4, comment="Reliable and well-documented. Handles edge cases cleanly.", ) print("Submitted:", result["review"]["id"]) # Read back data = get_reviews(MODEL_ID) print(f"Average: {data['average_rating']} across {data['total']} review(s)") for review in data["reviews"]: user = review.get("users") or {} print(f" ★{review['rating']} {user.get('username', 'unknown')}: {review['comment'][:60]}") ``` #### Handling the duplicate-review case ```python theme={null} import requests def safe_submit_review(model_id, model_type, rating, comment): try: return submit_review(model_id, model_type, rating, comment) except requests.HTTPError as exc: if exc.response.status_code == 409: print("Already reviewed this item — skipping.") return None raise ``` *** ### JavaScript / TypeScript ```typescript theme={null} const API_KEY = process.env.SWARMS_API_KEY!; const BASE_URL = "https://swarms.world"; interface SubmitReviewPayload { model_id: string; model_type: "agent" | "prompt" | "tool"; rating: 1 | 2 | 3 | 4 | 5; comment: string; } interface Review { id: string; model_id: string; model_type: string; rating: number; comment: string; created_at: string; } interface ReviewWithUser extends Review { users: { full_name: string | null; username: string | null; avatar_url: string | null; } | null; } interface SubmitReviewResponse { success: true; review: Review; } interface GetReviewsResponse { reviews: ReviewWithUser[]; average_rating: number | null; total: number; } /** Submit a rating and comment for an agent, prompt, or tool. */ async function submitReview(payload: SubmitReviewPayload): Promise<SubmitReviewResponse> { const res = await fetch(`${BASE_URL}/api/reviews`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(`${res.status} — ${body.error ?? "Unknown error"}`); } return res.json() as Promise<SubmitReviewResponse>; } /** Fetch all reviews for a given item. No API key required. */ async function getReviews(modelId: string): Promise<GetReviewsResponse> { const url = new URL(`${BASE_URL}/api/reviews`); url.searchParams.set("model_id", modelId); const res = await fetch(url.toString()); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(`${res.status} — ${body.error ?? "Unknown error"}`); } return res.json() as Promise<GetReviewsResponse>; } // ── Example usage ───────────────────────────────────────────────────────── const MODEL_ID = "d4f2a1b3-9c8e-4f1d-b2a7-3e5c6d8f0a2b"; // Submit const { review } = await submitReview({ model_id: MODEL_ID, model_type: "agent", rating: 5, comment: "Best tool in the marketplace for document parsing.", }); console.log("Saved review ID:", review.id); // Read back const { reviews, average_rating, total } = await getReviews(MODEL_ID); console.log(`${total} review(s), average ${average_rating ?? "N/A"} stars`); reviews.forEach((r) => { console.log(` ★${r.rating} ${r.users?.username ?? "unknown"}: ${r.comment}`); }); ``` #### Handling the `409 Conflict` gracefully ```typescript theme={null} async function submitReviewSafe(payload: SubmitReviewPayload) { const res = await fetch(`${BASE_URL}/api/reviews`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(payload), }); if (res.status === 409) { console.warn("Already reviewed this item — skipping."); return null; } if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(`${res.status} — ${body.error ?? "Unknown error"}`); } return res.json() as Promise<SubmitReviewResponse>; } ``` *** ## Notifications When a review is saved, the platform automatically sends an email notification to the owner of the reviewed item. This happens asynchronously — it does not delay or affect the API response. The email is **not sent** when: * The reviewer and the item owner are the same user account. * The item cannot be found in the database (e.g. invalid `model_id`). * The owner's account has no registered email address. Email delivery failures are silently logged and never propagated to the caller. *** ## Changelog | Date | Change | | ---------- | -------------------------------------------------------------- | | 2026-04-13 | Initial release of `POST /api/reviews` and `GET /api/reviews`. | # Share and Discover Source: https://docs.swarms.ai/docs/marketplace/share_and_discover Discover community-built agents, prompts, and tools on the Swarms Marketplace. The Swarms Marketplace (`https://swarms.world`) is a vibrant community hub where developers, researchers, and agent enthusiasts share and discover cutting-edge agent tools, agents, and prompts. This collaborative platform empowers you to leverage the collective intelligence of the Swarms community while contributing your own innovations. ## What You Can Discover ### 🤖 Agents Ready-to-use agent agents for specific tasks and industries: * **Specialized Agents**: From healthcare diagnostics to financial analysis * **Multi-Agent Systems**: Collaborative agent swarms for complex workflows * **Industry Solutions**: Pre-built agents for healthcare, finance, education, and more * **Custom Implementations**: Unique agent architectures and approaches ### 💡 Prompts System prompts and instructions that define agent behavior: * **Role-Specific Prompts**: Behavioral psychologist, documentation specialist, financial advisor * **System Templates**: Production-grade prompts for various use cases * **Collaborative Frameworks**: Multi-agent coordination prompts * **Task-Specific Instructions**: Optimized prompts for specific workflows ### 🛠️ Tools APIs, integrations, and utilities that extend agent capabilities: * **API Integrations**: Connect to external services and data sources * **Data Fetchers**: Tools for retrieving information from various platforms * **Workflow Utilities**: Helper functions and automation tools * **Communication Tools**: Integrations with messaging platforms and services ### 📦 Bundles Curated collections that package agents and prompts into a single, shareable toolkit: * **Research Stacks**: Research, summarization, and citation agents and prompts bundled together * **Team Onboarding Kits**: A vetted set of tools to get new teammates productive fast * **Custom Prompts**: Inline prompts written directly into the bundle, without a standalone listing * **Related Links**: Supporting docs, GitHub repos, or demos alongside the bundled items See the [Bundles](/docs/marketplace/bundles) guide for details, or publish one programmatically via the [Bundles API](/docs/marketplace/bundles-api). ## Browsing and Discovery ### Category-Based Navigation **Industry Categories:** * **Healthcare**: Medical diagnosis, patient care, research tools * **Education**: Learning assistants, curriculum development, assessment tools * **Finance**: Trading bots, market analysis, financial planning * **Research**: Academic paper fetchers, data analysis, literature review * **Public Safety**: Risk assessment, emergency response, safety monitoring * **Marketing**: Content creation, campagentgn optimization, audience analysis * **Sales**: Lead generation, customer engagement, sales automation * **Customer Support**: Chatbots, issue resolution, knowledge management ### Trending Section Discover the most popular and highly-rated content in the community: * **Top-Rated Items**: Content with 5-star ratings from users * **Community Favorites**: Most shared and downloaded items * **Recent Additions**: Latest contributions to the marketplace * **Featured Content**: Curated selections highlighting exceptional work ### Search and Filtering * **Keyword Search**: Find specific tools, agents, or prompts by name or description * **Category Filters**: Browse within specific industry verticals * **Rating Filters**: Filter by community ratings and reviews * **Tag-Based Discovery**: Explore content by relevant tags and keywords ## Contributing to the Marketplace ### Why Share Your Work? **🌟 Community Impact** * Help fellow developers solve similar challenges * Contribute to the collective advancement of agent technology * Build your reputation in the agent community **📈 Professional Growth** * Showcase your expertise and innovative solutions * Receive feedback and suggestions from the community * Network with like-minded professionals and researchers **🔄 Knowledge Exchange** * Learn from others who use and modify your contributions * Discover new approaches and improvements to your work * Foster collaborative innovation and problem-solving **🏆 Recognition** * Get credited for your contributions with author attribution * Build a portfolio of public agent implementations * Gagentn visibility in the growing Swarms ecosystem ## How to Submit Content ### Adding a Prompt Prompts are the foundation of agent behavior - share your carefully crafted instructions with the community. **Step-by-Step Process:** 1. **Click "Add Prompt"** from the marketplace interface 2. **Fill Required Fields:** * **Name**: Descriptive title that clearly indicates the prompt's purpose * **Description**: Detagentled explanation of what the prompt does and when to use it * **Prompt**: The complete system prompt or instruction text 3. **Enhance Your Submission:** * **Add Image**: Upload a visual representation (images up to 5MB, GIFs up to 35MB, videos up to 50MB) * **Select Categories**: Choose relevant industry categories * **Add Tags**: Include searchable keywords and descriptors 4. **Submit**: Review and submit your prompt to the community **Best Practices for Prompts:** * **Be Specific**: Clearly define the agent's role and expected behavior * **Include Context**: Provide background information and use case scenarios * **Test Thoroughly**: Ensure your prompt produces consistent, high-quality results * **Document Parameters**: Explagentn any variables or customization options ### Submitting an Agent Agents are complete agent implementations - share your working solutions with the community. **Step-by-Step Process:** 1. **Click "Add Agent"** from the marketplace interface 2. **Complete Required Information:** * **Name**: Clear, descriptive agent name * **Description**: Comprehensive explanation of functionality and use cases * **Agent Code**: Complete, working implementation * **Language**: Select the programming language (Python, etc.) 3. **Optimize Discoverability:** * **Categories**: Choose appropriate industry verticals * **Image**: Add a representative image or diagram * **Tags**: Include relevant keywords for searchability 4. **Submit**: Finalize and share your agent with the community **Agent Submission Guidelines:** * **Complete Implementation**: Provide fully functional, tested code * **Clear Documentation**: Include usage instructions and configuration detagentls * **Error Handling**: Implement robust error handling and validation * **Dependencies**: List all required libraries and dependencies * **Examples**: Provide usage examples and expected outputs ### Adding Tools Tools extend the capabilities of the Swarms ecosystem - share your integrations and utilities. **What Makes a Great Tool:** * **Solves Real Problems**: Addresses common pagentn points or workflow gaps * **Easy Integration**: Simple to implement and configure * **Well Documented**: Clear instructions and examples * **Reliable Performance**: Tested and optimized for production use ### Adding a Bundle Bundles package existing agents and prompts—plus your own custom prompts—into a single reusable toolkit. **Step-by-Step Process:** 1. **Click "Add Bundle"** from the marketplace interface (or select "Bundle" as the product type at [swarms.world/publish](https://swarms.world/publish)) 2. **Fill Required Fields:** * **Name**: Descriptive title (min. 2 characters) * **Description**: What the bundle is for and who it's for 3. **Add Items**: Reference existing agents/prompts by marketplace URL, or write custom prompts inline (name, description, content). A bundle needs at least one item. 4. **Enhance Your Submission:** Add a cover image, comma-separated tags, and optional related links (docs, GitHub, demos) 5. **Submit**: Review and publish—bundles are free to create and free to access Bundles can also be published programmatically via the [Bundles API](/docs/marketplace/bundles-api) (`POST /api/v1/publish/bundle`), which is handy for CI pipelines or bulk-publishing curated kits. ## Content Quality Guidelines ### Writing Effective Descriptions **For All Submissions:** * **Start with Purpose**: Lead with what your contribution does * **Explagentn Benefits**: Highlight the value and use cases * **Include Technical Detagentls**: Mention key features and capabilities * **Provide Context**: Explagentn when and why to use your contribution **Example Description Structure:** ``` [Brief summary of what it does] Key Features: - [Feature 1 with benefit] - [Feature 2 with benefit] - [Feature 3 with benefit] Use Cases: - [Scenario 1] - [Scenario 2] - [Scenario 3] Technical Detagentls: - [Implementation notes] - [Requirements or dependencies] - [Configuration options] ``` ### Choosing Categories and Tags **Categories:** * Select all relevant industry verticals * Consider cross-industry applications * Choose the primary category first **Tags:** * Include technical keywords (API names, frameworks, models) * Add functional descriptors (automation, analysis, generation) * Include use case keywords (customer service, data processing, content creation) * Use common terminology that others would search for ### Visual Assets **Image Guidelines:** * **File Size**: Images up to 5MB, GIFs up to 35MB, videos up to 50MB * **Recommended Types**: Screenshots, diagrams, logos, workflow illustrations * **Quality**: High-resolution images that clearly represent your contribution * **Content**: Visual representations of functionality, architecture, or results ## Community Engagement ### Rating and Reviews **As a User:** * Rate content honestly based on quality and usefulness * Leave constructive feedback to help creators improve * Share your experiences and modifications **As a Creator:** * Respond to feedback and questions * Update your submissions based on community input * Engage with users who implement your solutions ### Building Your Reputation **Consistency**: Regularly contribute high-quality content **Responsiveness**: Engage with community feedback and questions **Innovation**: Share unique approaches and creative solutions **Collaboration**: Build upon and improve existing community contributions ### What Makes Content Successful **Clear Value Proposition**: Immediately obvious benefits and use cases **Production Ready**: Fully functional, tested implementations **Good Documentation**: Clear instructions and examples **Active Magentntenance**: Regular updates and community engagement **Unique Approach**: Novel solutions or creative implementations ## Getting Started ### For New Contributors 1. **Explore First**: Browse existing content to understand community standards 2. **Start Small**: Begin with a simple but useful contribution 3. **Focus on Quality**: Prioritize completeness and documentation over quantity 4. **Engage**: Participate in discussions and provide feedback to others ### For Experienced Developers 1. **Share Expertise**: Contribute advanced implementations and frameworks 2. **Mentor Others**: Provide feedback and suggestions to new contributors 3. **Lead Innovation**: Introduce cutting-edge approaches and techniques 4. **Build Ecosystems**: Create complementary tools and integrations ## Best Practices Summary ### Before Submitting * ✅ Test your contribution thoroughly * ✅ Write clear, comprehensive documentation * ✅ Choose appropriate categories and tags * ✅ Create or find a representative image * ✅ Review similar existing content ### After Submitting * ✅ Monitor for community feedback * ✅ Respond to questions and comments * ✅ Update based on user suggestions * ✅ Share your contribution on social platforms * ✅ Continue improving and iterating ## Join the Community The Swarms Marketplace thrives on community participation. Whether you're sharing a simple prompt or a complex multi-agent system, your contribution makes the entire ecosystem stronger. Start exploring, contributing, and collaborating today! **Ready to contribute?** Visit `https://swarms.world` and click "Add Prompt," "Add Agent," "Add Tool," or "Add Bundle" to share your innovation with the world. Together, we're building the future of agent collaboration, one contribution at a time. # Token Launch API Source: https://docs.swarms.ai/docs/marketplace/token-launch-api Create a minimal agent listing and launch an associated token on Solana in a single request **POST** `https://swarms.world/api/token/launch` Creates a minimal agent listing and launches an associated token on Solana (via Jupiter). Only name, description, ticker, private key, and optional image are required. The agent is created with placeholder code and default metadata; the token is created and linked in a single request. Token creation costs approximately **0.04 SOL** (paid from the wallet associated with the private key). **Image flow:** If you send a raw image (file or base64), the endpoint uploads it to **Supabase Storage** first, then sends the resulting Supabase URL to Jupiter for token metadata. You can also pass an existing image URL. *** ## Request ### Headers | Name | Type | Required | Description | | --------------- | ------ | -------- | ----------------------------------------------------------------------------------------- | | `Authorization` | string | Yes | Bearer token. Use your API key: `Bearer YOUR_API_KEY`. | | `Content-Type` | string | Yes | Either `application/json` (for JSON body) or `multipart/form-data` (for raw file upload). | ### Body Parameters You can send the request in two ways: **Option A — JSON** (`Content-Type: application/json`) | Parameter | Type | Required | Default | Description | | --------------- | ------- | -------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | string | Yes | — | Display name of the agent. Minimum 2 characters. | | `description` | string | Yes | — | Description of the agent. Cannot be empty. | | `ticker` | string | Yes | — | Token symbol (e.g. `MAG`, `SWARM`). 1–10 characters; only letters and numbers. Automatically uppercased. | | `private_key` | string | Yes | — | Wallet private key used to sign the token-creation transaction. Accepted formats: JSON array of 64 bytes, base64 string, or base58 string. Must correspond to the creator wallet. | | `image` | string | No | — | Agent/token image. **URL** (`https://...` or `http://...`): used as-is. **Base64** (data URL or raw): uploaded to Supabase Storage, then the Supabase URL is sent to Jupiter. Omit for no image. | | `fee_selection` | string | No | `"market"` | Fee tier for the bonding curve. `"frenzy"` uses a 2× fee multiplier (higher fees, more visibility on the Frenzy leaderboard). `"market"` uses the standard fee. | | `quote_mint` | string | No | `"SOL"` | Quote currency for the bonding curve. `"SOL"` (default) or `"USDC"`. Determines the denomination of the initial and migration market caps. | | `vault_mode` | boolean | No | `false` | Holders-only view gating. When `true`, the agent's entity page is blurred for non-holders and shows a buy CTA; any non-zero balance of the launched token unlocks it. Creators always have access. | **Option B — Multipart** (`Content-Type: multipart/form-data`) | Field | Type | Required | Description | | --------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `name` | string | Yes | Same as above. | | `description` | string | Yes | Same as above. | | `ticker` | string | Yes | Same as above. | | `private_key` | string | Yes | Same as above. | | `image` | file | No | Raw image file (e.g. PNG, JPEG, WebP, GIF). Uploaded to Supabase Storage, then the Supabase URL is sent to Jupiter. Omit for no image. | | `fee_selection` | string | No | Same as JSON option above. | | `quote_mint` | string | No | Same as JSON option above. | | `vault_mode` | string | No | Same as JSON option above (send `"true"` or `"false"`). | *** ## Response ### Success (HTTP 200) | Field | Type | Description | | --------------- | -------------- | ------------------------------------------------------------------- | | `success` | boolean | Always `true` on success. | | `id` | string | UUID of the created agent in the database. | | `listing_url` | string | Full URL to the agent page, e.g. `https://swarms.world/agent/{id}`. | | `tokenized` | boolean | Always `true` for this endpoint. | | `token_address` | string \| null | Solana mint address of the created token. | | `pool_address` | string \| null | Pool or config address for the token, when available. | **Example success response:** ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000", "tokenized": true, "token_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "pool_address": "9yZ...configKey" } ``` ### HTTP Status Codes | Code | Meaning | | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `200` | Success; agent created and token launched. | | `400` | Bad request: validation failed (body params), invalid private key, **insufficient SOL balance** (creator wallet must have ≥ 0.04 SOL), tokenization failed, or content validation failed. | | `401` | Unauthorized: missing or invalid API key. Response includes a user-friendly message and `how_to_get_key` pointing to `https://swarms.world/platform/api-keys`. | | `405` | Method not allowed; only POST is accepted. | | `429` | Too many requests; daily agent limit exceeded. | | `500` | Internal server error, tokenization error, or database error. | ### Example Requests <CodeGroup> ```bash cURL (minimal) theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My Token Agent", "description": "An agent launched and tokenized via the Token Launch API.", "ticker": "MAG", "private_key": "[1,2,3,...]" }' ``` ```bash cURL (frenzy + USDC) theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "My Frenzy Agent", "description": "Launched in frenzy mode with a USDC-denominated bonding curve.", "ticker": "FRNZ", "private_key": "[1,2,3,...]", "fee_selection": "frenzy", "quote_mint": "USDC" }' ``` ```python Python theme={null} import requests BASE_URL = "https://swarms.world" API_KEY = "YOUR_API_KEY" payload = { "name": "My Token Agent", "description": "An agent launched and tokenized via the Token Launch API.", "ticker": "MAG", "private_key": "[1,2,3,...]", # Optional fields: # "image": "https://example.com/agent-icon.png", # "fee_selection": "frenzy", # "frenzy" | "market" (default) # "quote_mint": "USDC", # "SOL" (default) | "USDC" } response = requests.post( f"{BASE_URL}/api/token/launch", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, ) data = response.json() if response.ok: print("Success:", data.get("listing_url"), "Token:", data.get("token_address")) else: print("Error:", data.get("message", data.get("error"))) ``` ```typescript TypeScript theme={null} const response = await fetch("https://swarms.world/api/token/launch", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ name: "My Token Agent", description: "An agent launched and tokenized via the Token Launch API.", ticker: "MAG", private_key: "[1,2,3,...]", // fee_selection: "frenzy", // "frenzy" | "market" (default) // quote_mint: "USDC", // "SOL" (default) | "USDC" }), }); const data = await response.json(); if (response.ok) { console.log("Success:", data.listing_url, "Token:", data.token_address); } else { console.error("Error:", data.message || data.error); } ``` ```go Go theme={null} package main import ( "bytes" "encoding/json" "net/http" ) const baseURL = "https://swarms.world" const apiKey = "YOUR_API_KEY" func main() { payload := map[string]string{ "name": "My Token Agent", "description": "An agent launched and tokenized via the Token Launch API.", "ticker": "MAG", "private_key": "[1,2,3,...]", // "fee_selection": "frenzy", // "quote_mint": "USDC", } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", baseURL+"/api/token/launch", bytes.NewBuffer(body)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, _ := client.Do(req) defer resp.Body.Close() // decode resp.Body for id, listing_url, token_address } ``` ```rust Rust theme={null} // Add reqwest and serde_json to Cargo.toml use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box<dyn std::error::Error>> { let client = Client::new(); let payload = json!({ "name": "My Token Agent", "description": "An agent launched and tokenized via the Token Launch API.", "ticker": "MAG", "private_key": "[1,2,3,...]", // "fee_selection": "frenzy", // "quote_mint": "USDC" }); let res = client .post("https://swarms.world/api/token/launch") .header("Authorization", "Bearer YOUR_API_KEY") .json(&payload) .send()?; let data: serde_json::Value = res.json()?; if res.status().is_success() { println!("Success: {} Token: {}", data["listing_url"], data["token_address"]); } else { println!("Error: {}", data["message"].as_str().unwrap_or("Unknown")); } Ok(()) } ``` </CodeGroup> **Multipart (raw image file):** Use `-F` for each field and `-F "image=@/path/to/agent-icon.png"` with cURL; with Python use `requests.post(..., files={"image": open("agent-icon.png", "rb")}, data={...})`. *** ## Error Responses All error responses share a common shape. Additional fields may be present depending on the error type. ### Error response body (4xx / 5xx) | Field | Type | Description | | ------------- | ---------------- | --------------------------------------------------------------------------------- | | `error` | string | Short error category (e.g. `Validation error`, `Authentication required`). | | `message` | string | Human-readable error description. | | `details` | string \| object | Extra context; may be a string or a structured object (e.g. validation `errors`). | | `status_code` | number | HTTP status code (same as the response status). | ### Authentication errors (401) | Field | Type | Description | | ---------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `how_to_get_key` | string | Canonical link to create or manage your API key: `https://swarms.world/platform/api-keys`. Use this URL (not the request host) so the link is correct when calling from any environment. | ### Validation errors (400) | Field | Type | Description | | -------- | ----- | -------------------------------------------------------------- | | `errors` | array | Zod-style validation errors (e.g. path and message per field). | ### Rate limit errors (429) | Field | Type | Description | | -------------- | ------ | ------------------------------------------- | | `currentUsage` | number | Current usage count for the limit. | | `limits` | object | Applied rate limit configuration. | | `resetTime` | string | When the limit resets (e.g. UTC timestamp). | ### Example error responses **Validation error (400):** ```json theme={null} { "error": "Validation error", "message": "Request validation failed", "details": { "fieldErrors": { "ticker": ["Ticker must contain only letters and numbers"], "name": ["Name must be at least 2 characters"] } }, "status_code": 400 } ``` **Authentication failed (401):** When the API key is missing or invalid, the response is normalized so you always get a clear message and the canonical API-keys link (not the request host): ```json theme={null} { "error": "Authentication failed", "message": "Invalid or missing API key. Please check your API key and try again.", "how_to_get_key": "https://swarms.world/platform/api-keys", "status_code": 401 } ``` **Insufficient SOL balance (400):** Returned when the creator wallet (derived from `private_key`) has less than 0.04 SOL. Token launch requires enough SOL for transaction fees and rent. ```json theme={null} { "error": "Insufficient SOL balance", "message": "Token launch requires at least 0.04 SOL in the creator wallet. Your balance is 0.0029 SOL. Please add SOL and try again.", "required_sol": 0.04, "current_balance_sol": 0.0029, "status_code": 400 } ``` **Tokenization failed (400):** ```json theme={null} { "error": "Tokenization failed", "message": "Failed to create token on Jupiter", "details": "The token creation process failed. Please verify your wallet credentials and try again.", "status_code": 400 } ``` *** ## Notes 1. **Private key formats**\ `private_key` is accepted as: * **JSON array**: 64 integers, e.g. `[1,2,3,...,64]` * **Base64**: 64-byte key encoded as base64 * **Base58**: 64-byte key encoded as base58 (e.g. Phantom export format) 2. **Ticker**\ Only uppercase letters and numbers; maximum 10 characters. Stored and returned in uppercase. 3. **Image (raw upload → Supabase → Jupiter)** * **Raw file (multipart)**: Send `image` as a file in `multipart/form-data`. The endpoint uploads it to Supabase Storage, then sends the Supabase URL to Jupiter. * **Base64 (JSON)**: Send `image` as a `data:image/...;base64,...` string or raw base64 in the JSON body. The endpoint uploads it to Supabase Storage, then sends the Supabase URL to Jupiter. * **URL**: Any publicly fetchable URL (e.g. an existing Supabase URL). Used as-is for Jupiter token metadata; no Supabase upload is performed.\ Image is optional; the token can be created without one. 4. **Frenzy mode (`fee_selection: "frenzy"`)**\ Frenzy mode routes the token through a 2× fee Jupiter API key, doubling the bonding curve fees. Tokens launched with `fee_selection: "frenzy"` appear on the Frenzy leaderboard for increased visibility. Omit this field or set it to `"market"` for standard fees. 5. **Quote mint (`quote_mint`)**\ Controls the denomination of the bonding curve. Market cap defaults are USD targets — `$3,246` initial and `$46,468` migration: * `"SOL"` (default): SOL-quoted pool (9 decimals). The USD targets are converted to SOL at the current spot price. * `"USDC"`: USDC-quoted pool (6 decimals). The USD targets are used directly.\ On-chain mint addresses: SOL = `So11111111111111111111111111111111111111112`, USDC = `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. 6. **Authentication**\ Uses the same API key as the rest of the Swarms Platform API. Create and manage keys at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). 7. **Rate limits**\ Subject to the same daily agent creation limits. See the [Marketplace API Overview](/docs/marketplace/api-overview) for limits and reset behavior. 8. **Error handling**\ Some errors are normalized for a better client experience: * **401 (missing or invalid API key):** The response body is always `error: "Authentication failed"`, `message: "Invalid or missing API key. Please check your API key and try again."`, and `how_to_get_key: "https://swarms.world/platform/api-keys"` (canonical link; never localhost or another host). * Other errors (validation, tokenization, rate limit) are forwarded with the same status code and body shape. *** ## See also * [Frenzy Launch Example](/docs/marketplace/token-launch-frenzy-example) – Complete walkthrough for launching a tokenized frenzy agent with 2× fees. * [Token Launch Batch API](/docs/marketplace/token-launch-batch-api) – Create multiple tokenized agents in a single request (1–50 tokens per call). * [Marketplace API Overview](/docs/marketplace/api-overview) – Overview, authentication, and other endpoints. # Token Launch Batch API Source: https://docs.swarms.ai/docs/marketplace/token-launch-batch-api Create multiple tokenized agents in a single request **POST** `https://swarms.world/api/token/launch/batch` Creates multiple tokenized agents in a single request. Each item in the batch is launched the same way as the [single Token Launch](/docs/marketplace/token-launch-api) endpoint: minimal agent listing plus token creation on Solana via Jupiter. You can use one private key for all tokens (top-level `private_key`) or a different key per token (or a mix of both). **Use cases:** Launch many agents from one wallet, or from multiple wallets in one call; bulk tokenization with consistent or per-item metadata. **Content type:** This endpoint accepts **JSON only** (`application/json`). For multipart or file uploads, use the single [Token Launch](/docs/marketplace/token-launch-api) endpoint per token. **Batch size:** Minimum 1 token, maximum **50** tokens per request. **Execution:** All tokens are processed in **parallel**. If some items fail (e.g. downstream Add Agent errors), the response uses HTTP **207 Multi-Status** and includes both successes and failures in `results`. *** ## Request ### Headers | Name | Type | Required | Description | | --------------- | ------ | -------- | ------------------------------------------------------ | | `Authorization` | string | Yes | Bearer token. Use your API key: `Bearer YOUR_API_KEY`. | | `Content-Type` | string | Yes | Must be `application/json`. | ### Body Parameters | Parameter | Type | Required | Description | | ------------- | ------ | ----------- | ------------------------------------------------------------------------------------------------- | | `private_key` | string | Conditional | Default private key for all tokens. Required if any token does not provide its own `private_key`. | | `tokens` | array | Yes | Array of token definitions (1–50 items). See **Token item** below. | **Token item** (each element of `tokens`): | Field | Type | Required | Description | | --------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `name` | string | Yes | Display name of the agent. Minimum 2 characters. | | `description` | string | Yes | Description of the agent. Cannot be empty. | | `ticker` | string | Yes | Token symbol (e.g. `MAG`, `SWARM`). 1–10 characters; only letters and numbers. Automatically uppercased. | | `private_key` | string | No | Overrides the top-level `private_key` for this token only. Use when different wallets create different tokens. | | `image` | string | No | Agent/token image. **URL** (`https://...` or `http://...`): used as-is. **Base64** (data URL or raw): uploaded to Supabase Storage, then the Supabase URL is sent to Jupiter. Omit for no image. | | `fee_selection` | string | No | Fee tier for this token's bonding curve: `"frenzy"` (2× fees, listed on the Frenzy leaderboard) or `"market"` (standard fees). | **Private key rule:** Every token must have a private key. Either set `private_key` at the top level (applies to all tokens that don't set their own) or set `private_key` on each token, or mix: some tokens use the default, others override with their own. ## Code examples by language The following table lists the same batch launch request implemented in each language. Use the tabs below to view or copy the code. | Language | Description | | ---------- | ------------------------------------- | | cURL | Raw HTTP request with `curl`. | | Python | Using `requests` (sync). | | TypeScript | Using `fetch` (Node or browser). | | Rust | Using `reqwest` (blocking). | | Go | Using `net/http` and `encoding/json`. | <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/token/launch/batch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "private_key": "[1,2,3,...]", "tokens": [ { "name": "Agent One", "description": "First.", "ticker": "ONE" }, { "name": "Agent Two", "description": "Second.", "ticker": "TWO" } ] }' ``` ```python Python theme={null} import requests BASE_URL = "https://swarms.world" API_KEY = "YOUR_API_KEY" payload = { "private_key": "[1,2,3,...]", "tokens": [ {"name": "Agent One", "description": "First agent.", "ticker": "ONE"}, {"name": "Agent Two", "description": "Second agent.", "ticker": "TWO"}, ], } response = requests.post( f"{BASE_URL}/api/token/launch/batch", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, ) data = response.json() if response.status_code == 200: print("All succeeded:", data["results"]) elif response.status_code == 207: print("Partial:", data["succeeded"], "ok,", data["failed"], "failed") for r in data["results"]: if not r["success"]: print(" Index", r["index"], ":", r["error"]) else: print("Error:", data.get("message", data.get("error"))) ``` ```typescript TypeScript theme={null} const BASE_URL = "https://swarms.world"; const API_KEY = "YOUR_API_KEY"; interface TokenItem { name: string; description: string; ticker: string; private_key?: string; image?: string; } interface BatchLaunchParams { private_key?: string; tokens: TokenItem[]; } interface BatchLaunchSuccess { success: boolean; total: number; succeeded: number; failed: number; results: Array< | { success: true; index: number; id: string; listing_url?: string; token_address?: string | null; pool_address?: string | null } | { success: false; index: number; error: string } >; failures?: Array<{ success: false; index: number; error: string }>; } async function launchBatch(params: BatchLaunchParams): Promise<BatchLaunchSuccess> { const response = await fetch(`${BASE_URL}/api/token/launch/batch`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify(params), }); const data = await response.json(); if (!response.ok && response.status !== 207) { throw new Error(data.message ?? data.error ?? "Batch launch failed"); } return data as BatchLaunchSuccess; } // Usage launchBatch({ private_key: "[1,2,3,...]", tokens: [ { name: "Agent One", description: "First.", ticker: "ONE" }, { name: "Agent Two", description: "Second.", ticker: "TWO" }, ], }) .then((res) => { console.log("Succeeded:", res.succeeded, "Failed:", res.failed); res.results.forEach((r) => { if (r.success) console.log(" ", r.index, r.listing_url); else console.log(" ", r.index, r.error); }); }) .catch((err) => console.error(err)); ``` ```rust Rust theme={null} // Add reqwest and serde_json to Cargo.toml use reqwest::blocking::Client; use serde_json::json; fn main() -> Result<(), Box<dyn std::error::Error>> { let client = Client::new(); let payload = json!({ "private_key": "[1,2,3,...]", "tokens": [ {"name": "Agent One", "description": "First.", "ticker": "ONE"}, {"name": "Agent Two", "description": "Second.", "ticker": "TWO"} ] }); let res = client .post("https://swarms.world/api/token/launch/batch") .header("Authorization", "Bearer YOUR_API_KEY") .header("Content-Type", "application/json") .json(&payload) .send()?; let data: serde_json::Value = res.json()?; if res.status().as_u16() == 200 { println!("All succeeded: {:?}", data["results"]); } else if res.status().as_u16() == 207 { println!( "Partial: {} ok, {} failed", data["succeeded"], data["failed"] ); for r in data["results"].as_array().unwrap_or(&vec![]) { if !r["success"].as_bool().unwrap_or(false) { println!(" Index {}: {}", r["index"], r["error"]); } } } else { println!("Error: {}", data["message"].as_str().unwrap_or("Unknown")); } Ok(()) } ``` ```go Go theme={null} package main import ( "bytes" "encoding/json" "fmt" "net/http" ) const baseURL = "https://swarms.world" const apiKey = "YOUR_API_KEY" func main() { payload := map[string]interface{}{ "private_key": "[1,2,3,...]", "tokens": []map[string]string{ {"name": "Agent One", "description": "First.", "ticker": "ONE"}, {"name": "Agent Two", "description": "Second.", "ticker": "TWO"}, }, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", baseURL+"/api/token/launch/batch", bytes.NewBuffer(body)) req.Header.Set("Authorization", "Bearer "+apiKey) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Request error:", err) return } defer resp.Body.Close() var data map[string]interface{} json.NewDecoder(resp.Body).Decode(&data) if resp.StatusCode == 200 { fmt.Println("All succeeded:", data["results"]) } else if resp.StatusCode == 207 { fmt.Printf("Partial: %v ok, %v failed\n", data["succeeded"], data["failed"]) for _, r := range data["results"].([]interface{}) { item := r.(map[string]interface{}) if !item["success"].(bool) { fmt.Printf(" Index %v: %v\n", item["index"], item["error"]) } } } else { fmt.Println("Error:", data["message"]) } } ``` </CodeGroup> *** *** ## Response ### Success – All tokens launched (HTTP 200) | Field | Type | Description | | ----------- | ------- | -------------------------------------------------------------------------------- | | `success` | boolean | `true` when all tokens were launched. | | `total` | number | Total number of tokens in the batch. | | `succeeded` | number | Number of tokens that were created successfully. | | `failed` | number | Number of tokens that failed (0 when status is 200). | | `results` | array | One entry per token, in **index order**. Each success entry has the shape below. | **Success result item** (each entry in `results` when that token succeeded): | Field | Type | Description | | --------------- | -------------- | ------------------------------------------------------------------- | | `success` | boolean | Always `true`. | | `index` | number | Zero-based index of the token in the request `tokens` array. | | `id` | string | UUID of the created agent in the database. | | `listing_url` | string | Full URL to the agent page, e.g. `https://swarms.world/agent/{id}`. | | `token_address` | string \| null | Solana mint address of the created token. | | `pool_address` | string \| null | Jupiter pool/config address for the token, when available. | ### Partial success – Some tokens failed (HTTP 207) When at least one token fails (e.g. Add Agent returns an error), the response status is **207 Multi-Status**. The body has the same structure as above, with: * `success`: `false` * `succeeded` + `failed`: counts of successful and failed items * `results`: array of **both** successful and failed items, sorted by `index` * `failures`: optional array of only the failed items (for convenience) **Failure result item** (entry in `results` when that token failed): | Field | Type | Description | | --------- | ------- | ------------------------------------------------------------ | | `success` | boolean | Always `false`. | | `index` | number | Zero-based index of the token in the request `tokens` array. | | `error` | string | Error message (e.g. from Add Agent or tokenization). | ### Error response body (4xx / 5xx) Request-level errors (validation, invalid key, insufficient SOL, wrong content type, etc.) return a single error object, not a batch result. | Field | Type | Description | | ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `error` | string | Short error category (e.g. `Validation error`, `Invalid private key`). | | `message` | string | Human-readable error description. | | `details` | string \| object | Optional; validation details or other context. | | `status_code` | number | HTTP status code. | | `token_index` | number | Optional; present for per-token errors (e.g. invalid private key or insufficient SOL) to indicate which token in `tokens` caused the error. | **Authentication errors (401)** from the downstream Add Agent call are returned as failed items in `results` (HTTP 207), not as a single 401 response. The error message in the failed result will indicate authentication failure. **Validation errors (400)** for the whole request (e.g. missing private key for all tokens, invalid JSON, or validation failure) include: | Field | Type | Description | | --------- | ------ | --------------------------------------------------------------- | | `details` | object | Often Zod-style `fieldErrors` for `tokens` or top-level fields. | **Insufficient SOL (400)** includes: | Field | Type | Description | | --------------------- | ------ | ------------------------------------------------------------- | | `token_index` | number | Index of the token whose creator wallet has insufficient SOL. | | `required_sol` | number | Minimum required SOL (0.04). | | `current_balance_sol` | number | Creator wallet balance at time of check. | *** ## HTTP Status Codes | Code | Meaning | | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `200` | All tokens launched successfully. | | `207` | Multi-Status: at least one token succeeded and at least one failed. Check `results` (or `failures`) for per-item outcome. | | `400` | Bad request: invalid JSON, validation failed, invalid private key, insufficient SOL for a token, or unsupported content type (e.g. not `application/json`). Use `token_index` when present to identify the failing token. | | `401` | Unauthorized: missing or invalid API key. (If Add Agent returns 401 for some items, those appear as failed entries in a 207 response.) | | `405` | Method not allowed; only POST is accepted. | | `429` | Too many requests; daily agent limit exceeded. | | `500` | Internal server error. | *** ## Examples ### Minimal request – one private key for all tokens ```json theme={null} POST https://swarms.world/api/token/launch/batch Authorization: Bearer YOUR_API_KEY Content-Type: application/json { "private_key": "[1,2,3,...]", "tokens": [ { "name": "Agent One", "description": "First agent.", "ticker": "ONE" }, { "name": "Agent Two", "description": "Second agent.", "ticker": "TWO" } ] } ``` ### Response examples by status Output JSON for each HTTP status. Use the tabs to switch between response types. <CodeGroup> ```json 200 Success theme={null} { "success": true, "total": 2, "succeeded": 2, "failed": 0, "results": [ { "success": true, "index": 0, "id": "550e8400-e29b-41d4-a716-446655440001", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440001", "token_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "pool_address": "9yZ...configKey" }, { "success": true, "index": 1, "id": "550e8400-e29b-41d4-a716-446655440002", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440002", "token_address": "8yLYtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsV", "pool_address": "9zA...configKey" } ] } ``` ```json 207 Partial success theme={null} { "success": false, "total": 2, "succeeded": 1, "failed": 1, "results": [ { "success": true, "index": 0, "id": "550e8400-e29b-41d4-a716-446655440001", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440001", "token_address": "7xKX...", "pool_address": "9yZ..." }, { "success": false, "index": 1, "error": "Agent with this name and content already exists." } ], "failures": [ { "success": false, "index": 1, "error": "Agent with this name and content already exists." } ] } ``` ```json 400 Validation (missing private key) theme={null} { "error": "Validation error", "message": "Request validation failed", "details": { "formErrors": ["Either provide a top-level private_key or a private_key for each token."], "fieldErrors": { "tokens": [] } }, "status_code": 400 } ``` ```json 400 Validation (invalid ticker) theme={null} { "error": "Validation error", "message": "Request validation failed", "details": { "fieldErrors": { "tokens": { "1": { "ticker": ["Ticker must contain only letters and numbers"] } } } }, "status_code": 400 } ``` ```json 400 Invalid private key theme={null} { "error": "Invalid private key", "message": "Invalid private key format. Must be JSON array, base64, or base58 string.", "token_index": 2, "status_code": 400 } ``` ```json 400 Insufficient SOL theme={null} { "error": "Insufficient SOL balance", "message": "Token at index 1 (Agent Two) requires at least 0.04 SOL. Creator wallet balance: 0.0029 SOL.", "token_index": 1, "required_sol": 0.04, "current_balance_sol": 0.0029, "status_code": 400 } ``` ```json 400 Unsupported content type theme={null} { "error": "Unsupported content type", "message": "Batch launch accepts application/json only.", "status_code": 400 } ``` </CodeGroup> ### Mixed private keys – default plus overrides ```json theme={null} { "private_key": "[default-wallet-key]", "tokens": [ { "name": "Agent A", "description": "Uses default key.", "ticker": "AGTA" }, { "name": "Agent B", "description": "Uses a different wallet.", "ticker": "AGTB", "private_key": "[other-wallet-key]" } ] } ``` ### Request with image URL and base64 ```json theme={null} { "private_key": "[1,2,3,...]", "tokens": [ { "name": "Agent With URL Image", "description": "Image from URL.", "ticker": "URLIMG", "image": "https://example.com/icon.png" }, { "name": "Agent With Base64 Image", "description": "Image as base64.", "ticker": "B64IMG", "image": "data:image/png;base64,iVBORw0KGgo..." } ] } ``` *** ## Notes 1. **Private key formats**\ Same as the single Token Launch API: * **JSON array**: 64 integers, e.g. `[1,2,3,...,64]` * **Base64**: 64-byte key encoded as base64 * **Base58**: 64-byte key encoded as base58 (e.g. Phantom export format) 2. **Ticker**\ Per token: 1–10 characters, letters and numbers only. Stored and returned in uppercase. 3. **Image** * **URL**: `https://...` or `http://...` is used as-is. * **Base64**: `data:image/...;base64,...` or raw base64 is uploaded to Supabase Storage; the resulting URL is sent to Jupiter. * Batch endpoint does **not** support multipart file upload; use the single Token Launch endpoint for file uploads. 4. **Authentication**\ Same API key as the rest of the Swarms Platform API. Create and manage keys at [https://swarms.world/platform/api-keys](https://swarms.world/platform/api-keys). If Add Agent returns 401 for some items, those appear as failed entries in a 207 response with an authentication-related error message. 5. **Rate limits**\ Subject to the same daily agent creation limits as Add Agent. Each token in the batch counts toward your limit. See the [Marketplace API Overview](/docs/marketplace/api-overview) for limits and reset behavior. 6. **Batch size**\ Minimum 1, maximum 50 tokens per request. For larger batches, send multiple requests. 7. **Order and indexing**\ `results` are sorted by `index` (the position in the request `tokens` array). Use `index` to correlate successes and failures with your input. 8. **Pre-validation and early exit**\ Before launching any token, the endpoint validates all private keys and (when RPC is available) checks SOL balance for each creator wallet. If any of these checks fail, the entire request returns 400 with `token_index` so you can fix that item and retry. 9. **Downstream behavior**\ Each token is created via the same Add Agent flow as the single Token Launch endpoint (placeholder agent, default metadata, `tokenized_on: true`). Failures (e.g. duplicate agent, tokenization error) are reported per item in `results` with HTTP 207. *** ## See also * [Token Launch (single)](/docs/marketplace/token-launch-api) – Create one token per request; supports JSON and multipart. * [Agents API](/docs/marketplace/agents-api) – Full agent creation API used internally by both launch endpoints. * [Marketplace API Overview](/docs/marketplace/api-overview) – Overview, authentication, and other endpoints. # Frenzy Launch Example Source: https://docs.swarms.ai/docs/marketplace/token-launch-frenzy-example Step-by-step guide to launching a tokenized agent in Frenzy mode with 2× bonding curve fees This guide walks through launching a tokenized agent with `fee_selection: "frenzy"` — a mode that doubles the bonding curve fees and places your token on the Frenzy leaderboard for increased visibility. **What you need:** * A Swarms API key ([get one here](https://swarms.world/platform/api-keys)) * A Solana wallet private key with at least **0.04 SOL** for transaction fees *** ## What is Frenzy mode? Setting `fee_selection: "frenzy"` routes your token launch through a 2× fee Jupiter API key. This: * **Doubles the bonding curve fees** collected from traders * **Lists your token on the Frenzy leaderboard**, giving it prominent placement for users browsing high-activity tokens * Has no effect on the token creation cost you pay (still \~0.04 SOL) You can combine Frenzy mode with either quote mint: * `"SOL"` (default) — SOL-denominated bonding curve * `"USDC"` — USDC-denominated bonding curve *** ## Quickstart <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Frenzy Research Agent", "description": "An AI research agent launched in Frenzy mode for maximum visibility.", "ticker": "FRNZ", "private_key": "[1,2,3,...]", "fee_selection": "frenzy", "quote_mint": "SOL" }' ``` ```python Python theme={null} import os import requests API_KEY = os.environ["SWARMS_API_KEY"] PRIVATE_KEY = os.environ["SWARMS_PRIVATE_KEY"] # base58, base64, or JSON array BASE_URL = "https://swarms.world" payload = { "name": "Frenzy Research Agent", "description": "An AI research agent launched in Frenzy mode for maximum visibility.", "ticker": "FRNZ", "private_key": PRIVATE_KEY, "fee_selection": "frenzy", "quote_mint": "SOL", } response = requests.post( f"{BASE_URL}/api/token/launch", headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", }, json=payload, ) data = response.json() if response.ok: print(f"Agent created: {data['listing_url']}") print(f"Token address: {data['token_address']}") print(f"Pool address: {data['pool_address']}") else: print(f"Error ({response.status_code}): {data.get('message', data.get('error'))}") if "required_sol" in data: print(f" Required SOL: {data['required_sol']} | Your balance: {data['current_balance_sol']}") ``` ```typescript TypeScript theme={null} const API_KEY = process.env.SWARMS_API_KEY!; const PRIVATE_KEY = process.env.SWARMS_PRIVATE_KEY!; interface FrenzyLaunchResult { success: true; id: string; listing_url: string; tokenized: true; token_address: string | null; pool_address: string | null; } async function launchFrenzyAgent(): Promise<FrenzyLaunchResult> { const response = await fetch("https://swarms.world/api/token/launch", { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Frenzy Research Agent", description: "An AI research agent launched in Frenzy mode for maximum visibility.", ticker: "FRNZ", private_key: PRIVATE_KEY, fee_selection: "frenzy", quote_mint: "SOL", }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message ?? data.error ?? "Token launch failed"); } return data as FrenzyLaunchResult; } launchFrenzyAgent() .then((res) => { console.log("Agent created: ", res.listing_url); console.log("Token address:", res.token_address); console.log("Pool address: ", res.pool_address); }) .catch(console.error); ``` </CodeGroup> *** ## With a USDC-denominated bonding curve Pass `"quote_mint": "USDC"` to price the bonding curve in USDC instead of SOL. The market cap targets are `$3,246` (initial) and `$46,468` (migration); a USDC-quoted pool uses those USD figures directly, while a SOL-quoted pool converts them to SOL at the current spot price. <CodeGroup> ```bash cURL theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Frenzy USDC Agent", "description": "Frenzy mode with a USDC-denominated bonding curve.", "ticker": "FUSD", "private_key": "[1,2,3,...]", "fee_selection": "frenzy", "quote_mint": "USDC" }' ``` ```python Python theme={null} payload = { "name": "Frenzy USDC Agent", "description": "Frenzy mode with a USDC-denominated bonding curve.", "ticker": "FUSD", "private_key": PRIVATE_KEY, "fee_selection": "frenzy", "quote_mint": "USDC", } response = requests.post( f"{BASE_URL}/api/token/launch", headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}, json=payload, ) data = response.json() if response.ok: print("Listed at:", data["listing_url"]) print("Token: ", data["token_address"]) else: print("Error:", data.get("message", data.get("error"))) ``` ```typescript TypeScript theme={null} const response = await fetch("https://swarms.world/api/token/launch", { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ name: "Frenzy USDC Agent", description: "Frenzy mode with a USDC-denominated bonding curve.", ticker: "FUSD", private_key: PRIVATE_KEY, fee_selection: "frenzy", quote_mint: "USDC", }), }); const data = await response.json(); console.log(response.ok ? data.listing_url : data.message); ``` </CodeGroup> *** ## With an image You can attach an agent icon. Pass an image URL, a base64 data URL, or upload a raw file via multipart. <CodeGroup> ```python Python (image URL) theme={null} payload = { "name": "Frenzy Agent With Icon", "description": "Frenzy launch with a custom agent icon.", "ticker": "FICO", "private_key": PRIVATE_KEY, "fee_selection": "frenzy", "quote_mint": "SOL", "image": "https://example.com/agent-icon.png", } ``` ```python Python (raw file upload) theme={null} import requests, os with open("agent-icon.png", "rb") as img: response = requests.post( "https://swarms.world/api/token/launch", headers={"Authorization": f"Bearer {os.environ['SWARMS_API_KEY']}"}, data={ "name": "Frenzy Agent With Icon", "description": "Frenzy launch with a raw image upload.", "ticker": "FICO", "private_key": os.environ["SWARMS_PRIVATE_KEY"], "fee_selection": "frenzy", "quote_mint": "SOL", }, files={"image": img}, ) data = response.json() print(data.get("listing_url") or data.get("message")) ``` ```bash cURL (raw file upload) theme={null} curl -X POST https://swarms.world/api/token/launch \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "name=Frenzy Agent With Icon" \ -F "description=Frenzy launch with a raw image upload." \ -F "ticker=FICO" \ -F "private_key=[1,2,3,...]" \ -F "fee_selection=frenzy" \ -F "quote_mint=SOL" \ -F "image=@/path/to/agent-icon.png" ``` </CodeGroup> *** ## Success response ```json theme={null} { "success": true, "id": "550e8400-e29b-41d4-a716-446655440000", "listing_url": "https://swarms.world/agent/550e8400-e29b-41d4-a716-446655440000", "tokenized": true, "token_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "pool_address": "9yZ...configKey" } ``` *** ## Common errors **Insufficient SOL (400):** The creator wallet needs at least 0.04 SOL. ```json theme={null} { "error": "Insufficient SOL balance", "message": "Token launch requires at least 0.04 SOL in the creator wallet. Your balance is 0.0029 SOL. Please add SOL and try again.", "required_sol": 0.04, "current_balance_sol": 0.0029, "status_code": 400 } ``` **Invalid API key (401):** ```json theme={null} { "error": "Authentication failed", "message": "Invalid or missing API key. Please check your API key and try again.", "how_to_get_key": "https://swarms.world/platform/api-keys", "status_code": 401 } ``` *** ## See also * [Token Launch API](/docs/marketplace/token-launch-api) — Full parameter reference. * [Token Launch Batch API](/docs/marketplace/token-launch-batch-api) — Launch up to 50 tokens in one request. * [API Keys](https://swarms.world/platform/api-keys) — Create and manage your API key. # Monetization Models Source: https://docs.swarms.ai/docs/marketplace/tokenization Publish and monetize your AI agents, prompts, and tools on the Swarms Marketplace The Swarms Marketplace allows you to publish and monetize your AI agents, prompts, and tools. Choose from three monetization options and make your products available to the Swarms ecosystem. <Info> **Launching products is only available through the web interface** at [swarms.world/launch](https://swarms.world/launch). There is no API for publishing. </Info> *** ## Overview When launching a product on the Swarms Marketplace, you'll need to: 1. **Choose a product type** - Agent, Prompt, or Tool 2. **Fill in required information** - Name, description, image, and use cases 3. **Select a monetization option** - Free, Paid, or Tokenization 4. **Submit for review** - All products undergo quality validation *** ## Product Types Choose the type that best fits what you're publishing: <Tabs> <Tab title="Agents"> Agents are autonomous AI entities **with executable code**. **Use for:** * Python or other language code implementations * Custom agent logic and behaviors * Integration with external tools and APIs * Solutions with package dependencies <Info> Agents require actual code that can be executed. Include types, docstrings, and specify package dependencies. </Info> </Tab> <Tab title="Prompts"> Prompts are system prompt templates **without any code**. **Use for:** * System prompts for LLM interactions * Instruction templates * Persona definitions * Task-specific prompt engineering <Note> Prompts are available via the Swarms Framework, API, and Chat interface. They can also be exported to ChatGPT and Claude. </Note> </Tab> <Tab title="Tools"> Tools are utility functions and integrations. **Use for:** * API connectors * Data processing utilities * External service integrations * Custom functions </Tab> </Tabs> *** ## Required Information All products require the following: <CardGroup> <Card title="Image" icon="image"> **Required** - A representative image for your product (max 60MB). Helps users identify and discover your listing. </Card> <Card title="Name" icon="tag"> **Required** - A descriptive name (minimum 2 characters) for your product. </Card> <Card title="Description" icon="align-left"> **Required** - Detailed description of what your product does and how to use it. </Card> <Card title="Use Cases" icon="lightbulb"> **Required** - At least one practical use case demonstrating your product's value. </Card> </CardGroup> ### Additional Fields * **Language** - Programming language (for agents) * **Requirements** - Package dependencies (for agents) * **Tags** - Comma-separated keywords for discoverability * **Category** - Product category * **Links** - Related URLs (GitHub, documentation, etc.) *** ## Monetization Options When publishing, you must choose **one** of three monetization options: <Tabs> <Tab title="Free"> ### Free Make your product freely available to all users at no cost. **Requirements:** * None **Best for:** * Open source projects * Community contributions * Building reputation * Showcasing capabilities </Tab> <Tab title="Paid"> ### Paid Set a fixed price in USD for your product. **Requirements:** * Minimum price: **\$0.01** * Wallet address for receiving payments **Best for:** * Premium content * Professional solutions * Specialized agents or prompts * Direct monetization </Tab> <Tab title="Tokenization"> ### Tokenization Create a unique token on the Solana blockchain for your product. <Warning> Tokenization costs **0.04 SOL** to cover blockchain transaction fees for minting your token. </Warning> **Requirements:** * Unique ticker symbol (max 10 characters, uppercase letters and numbers only) * 0.04 SOL fee **Ticker Examples:** `AGENT`, `MYBOT`, `DATA123`, `RESEARCH` **Best for:** * Tradeable assets * Building token-based ecosystems * Premium positioning * Long-term value creation </Tab> </Tabs> <Warning> You can only select **one** monetization option per product. Choose the option that best aligns with your goals. </Warning> *** ## How to Launch <Steps> <Step title="Sign In"> Log in to your Swarms account at [swarms.world](https://swarms.world) </Step> <Step title="Go to Launch Portal"> Navigate to [swarms.world/launch](https://swarms.world/launch) </Step> <Step title="Select Product Type"> Choose **Agent**, **Prompt**, or **Tool** </Step> <Step title="Upload Image"> Add a representative image for your product (required, max 60MB) </Step> <Step title="Fill in Details"> Complete name, description, and use cases </Step> <Step title="Choose Monetization"> Select one option: **Free**, **Paid**, or **Tokenization** * If Paid: Set price and wallet address * If Tokenization: Enter ticker symbol and pay 0.04 SOL fee </Step> <Step title="Submit"> Submit your product for quality validation </Step> </Steps> *** ## Import from GitHub You can import agents directly from a public GitHub repository: <Steps> <Step title="Prepare Repository"> Ensure your GitHub repository is **public** </Step> <Step title="Enter URL"> Paste your public GitHub repository URL in the import field </Step> <Step title="Import"> Click **Import** to pull the repository contents </Step> </Steps> <Warning> Private repositories are not currently supported. </Warning> *** ## Quality Validation All submissions undergo automated quality validation: <AccordionGroup> <Accordion title="Duplicate Detection"> Checks for duplicate content to ensure originality and prevent spam. </Accordion> <Accordion title="Quality Assessment"> Evaluates code completeness, documentation quality, and best practices. </Accordion> <Accordion title="Security Scanning"> Scans agent code for potential security issues and malicious content. </Accordion> <Accordion title="Trustworthiness Scoring"> Assigns a trust score based on quality metrics. </Accordion> </AccordionGroup> *** ## After Publishing Once published, your products are available across Swarms platforms: * **Swarms Python Framework** - Use programmatically in applications * **Swarms API** - Query and retrieve via REST API * **Swarms Chat** - Browse and use at [swarms.world/chat](https://swarms.world/chat) * **Marketplace** - Discoverable by all users at [swarms.world/marketplace](https://swarms.world/marketplace) *** ## Best Practices <CardGroup> <Card title="High-Quality Images" icon="image"> Use clear, professional images that represent your product well. </Card> <Card title="Detailed Descriptions" icon="file-lines"> Write comprehensive descriptions explaining features, use cases, and benefits. </Card> <Card title="Multiple Use Cases" icon="list-check"> Provide diverse use cases to help users understand your product's versatility. </Card> <Card title="Descriptive Tickers" icon="hashtag"> For tokenization, choose ticker symbols that relate to your product's purpose. </Card> </CardGroup> *** ## Support Need help? Reach out through: * **Discord**: [Join our community](https://discord.gg/EamjgSaEQf) * **Technical Support**: [Schedule a call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) # Tokenization Details Source: https://docs.swarms.ai/docs/marketplace/tokenization_details Learn about token creation costs and bonding curve progression for tokenized agents and prompts Tokenization allows you to create a unique token on the Solana blockchain for your agent or prompt, enabling tradeable assets and token-based ecosystems. <Info> Tokenization applies to both **agents** and **prompts** published on the Swarms Marketplace. </Info> *** ## Token Creation Cost 🪙 To officially tokenize your agent or associated prompt, you must pay a token creation fee to cover blockchain transaction costs. <CardGroup> <Card title="Creation Fee" icon="coins"> **0.04 SOL** Approximately **\$4 USD** at current rates (fluctuates with SOL price) </Card> <Card title="Payment Method" icon="wallet"> Paid during the tokenization process when launching your product One-time fee per tokenized product </Card> </CardGroup> <Warning> The USD equivalent of 0.04 SOL fluctuates with the current SOL price. The fee is always charged in SOL, not USD. </Warning> *** ## Bonding Curve Progression Tokenized products use a bonding curve mechanism that determines token pricing and market dynamics. The bonding curve progresses through different market cap stages. ### Market Cap Stages <Steps> <Step title="Initial Market Cap"> Your token starts at **18 SOL equivalent** when first created. This represents the initial valuation of your tokenized product. </Step> <Step title="Market Growth"> As users purchase tokens, the market cap increases along the bonding curve. Early buyers get better prices, while later buyers pay more as demand increases. </Step> <Step title="Graduation Market Cap"> When the market cap reaches **400 SOL equivalent**, the token graduates from the virtual pool. At this point, the token becomes fully tradeable on decentralized exchanges. </Step> </Steps> ### Key Metrics <CardGroup> <Card title="Initial Market Cap" icon="chart-line"> **18 SOL** Starting valuation when token is created </Card> <Card title="Graduation Market Cap" icon="trophy"> **400 SOL** Target market cap for graduation from virtual pool </Card> </CardGroup> *** ## How Bonding Curves Work Bonding curves create a predictable pricing mechanism that rewards early adopters while providing liquidity: <AccordionGroup> <Accordion title="Price Discovery"> Token price increases as more tokens are purchased, creating natural price discovery based on demand. </Accordion> <Accordion title="Early Adopter Rewards"> Users who purchase tokens early benefit from lower prices, incentivizing early participation. </Accordion> <Accordion title="Liquidity Provision"> The bonding curve provides continuous liquidity without requiring traditional market makers. </Accordion> <Accordion title="Graduation Benefits"> Once graduated, tokens can be traded on DEXs, providing additional liquidity and trading opportunities. </Accordion> </AccordionGroup> *** ## Tokenization Process When you choose tokenization as your monetization option: <Steps> <Step title="Select Tokenization"> Choose **Tokenization** as your monetization method when launching your agent or prompt. </Step> <Step title="Enter Ticker Symbol"> Provide a unique ticker symbol (max 10 characters, uppercase letters and numbers only). Examples: `AGENT`, `MYBOT`, `DATA123`, `RESEARCH` </Step> <Step title="Pay Creation Fee"> Pay the **0.04 SOL** token creation fee to cover blockchain transaction costs. </Step> <Step title="Token Creation"> Your token is minted on the Solana blockchain with an initial market cap of **18 SOL**. </Step> <Step title="Market Growth"> As users purchase your token, the market cap grows along the bonding curve toward **400 SOL**. </Step> <Step title="Graduation"> Upon reaching **400 SOL** market cap, your token graduates and becomes fully tradeable. </Step> </Steps> *** ## Considerations <CardGroup> <Card title="Cost Fluctuation" icon="dollar-sign"> SOL prices fluctuate, so the USD equivalent of 0.04 SOL will vary over time. Always check current SOL prices before tokenizing. </Card> <Card title="One-Time Fee" icon="receipt"> The 0.04 SOL fee is a one-time payment per tokenized product. No recurring fees for maintaining the token. </Card> <Card title="Market Cap Targets" icon="target"> The 18 SOL initial and 400 SOL graduation caps are fixed in SOL terms. USD values will fluctuate with SOL price. </Card> <Card title="Graduation Timeline" icon="clock"> Time to graduation depends on market demand and token purchases. Popular products may graduate faster than others. </Card> </CardGroup> *** ## Best Practices <CardGroup> <Card title="Choose Descriptive Tickers" icon="hashtag"> Select ticker symbols that clearly relate to your product's purpose and are memorable. </Card> <Card title="Market Your Token" icon="megaphone"> Promote your tokenized product to drive demand and accelerate toward graduation. </Card> <Card title="Monitor Market Cap" icon="chart-bar"> Track your token's progress toward the 400 SOL graduation target. </Card> <Card title="Engage Early Adopters" icon="users"> Encourage early token purchases to build momentum and reach graduation faster. </Card> </CardGroup> *** ## Support Need help with tokenization? Reach out through: * **Discord**: [Join our community](https://discord.gg/EamjgSaEQf) * **Technical Support**: [Schedule a call](https://cal.com/swarms/swarms-technical-support?overlayCalendar=true) * **Launch Portal**: [swarms.world/launch](https://swarms.world/launch) # Marketplace Endpoints Source: https://docs.swarms.ai/docs/marketplace/user-marketplace-endpoints Complete reference of Swarms Marketplace endpoints for managing your agents, prompts, products, fees, token launches, and reviews Reference for the Marketplace REST endpoints that require a **Swarms API key**. * **Base URL:** `https://swarms.world` * **Get an API key:** [swarms.world/platform/api-keys](https://swarms.world/platform/api-keys) ## Authentication Send your API key in the `Authorization` header: ```text theme={null} Authorization: Bearer YOUR_API_KEY ``` Every endpoint below requires a valid key (returns `401` otherwise). Endpoints marked *(API key or session)* also accept a logged-in session cookie, but the API key path is always available. ### Common status codes | Code | Meaning | | ----- | --------------------------------------------------- | | `200` | Success | | `207` | Multi-status (partial success — batch token launch) | | `400` | Bad request / validation error | | `401` | Missing or invalid API key | | `403` | Forbidden (e.g. paid content without access) | | `404` | Not found | | `405` | Method not allowed | | `409` | Conflict (e.g. already reviewed) | | `429` | Rate limit exceeded | | `500` | Internal server error | *** ## Products & Fees ### `GET /api/product/list` List every product the authenticated user has posted (agents, prompts, tools, bundles). * **Query:** `type` — `agent` | `prompt` | `tool` | `bundle` | `all` (default `all`) * **Returns:** `user_id`, `total`, `counts { agents, prompts, tools, bundles }`, `products[] { id, type, name, description, created_at, url }` (newest-first) <Card title="Full reference" icon="list" href="/docs/marketplace/list-products-api"> List Products API — request/response details and code examples </Card> ### `GET /api/product/fees` Creator fees (via the Jupiter partner API) generated by one of your **tokenized** products, in the pool's quote currency (SOL by default). * **Query (one of):** `ticker` · `id` (UUID) · `ca` (token address) · `url` (full Swarms URL) · `product` (auto-detects which of the four) * **Returns:** `name`, `uuid`, `ca`, `ticker`, `quoteMint`, `claimedFees`, `unclaimedFees`, `totalFees`, `usdcEquivalent`, `isAvailable`, `timestamp` * **Notes:** Only tokenized agents/prompts have fees. If no fee data exists yet, amounts return `0`. <Card title="Full reference" icon="coins" href="/docs/marketplace/product-fees-api"> Product Fees API — request/response details and code examples </Card> ### `POST /api/user-products` Authenticated user's products across prompts/agents/tools with business-model + summary stats. *(API key or session)* * **Body:** `page`, `limit`, `product_type` — `all` | `prompts` | `agents` | `tools` * **Returns:** `prompts[]`, `agents[]`, `tools[]`, `pagination`, `summary` * **Notes:** Superseded by `GET /api/product/list` (which also covers bundles + `created_at`). ### `GET|POST /api/get-tokenized-products` Authenticated user's tokenized agents/prompts (those with a `token_address`). *(API key or session)* * **Params (query or body):** `type` — `all` | `agent` | `prompt`; `page`, `limit` * **Returns:** `data[] { id, name, type, token_address, listing_url }`, `counts`, `pagination` *** ## Agents ### `POST /api/add-agent` Create a marketplace agent listing; optionally tokenize it and upload an image. *(API key or session)* * **Body (core):** `name`, `agent` (code, nullable), `description`, `useCases[]`, `requirements[]`, `language`, `tags`, `is_free`, `price_usd`, `category`, `status`, `image_url` / `image_base64` / `file_path`, `links[]`, `seller_wallet_address`, `payment_method`, `x402_url`, `mcp_url` * **Body (tokenization):** `tokenized_on`, `ticker`, `creator_wallet`, `private_key`, `fee_selection` (`frenzy` | `market`), `quote_mint` (`SOL` | `USDC`), `vault_mode` * **Returns:** `success`, `id`, `listing_url`, `tokenized`, `token_address`, `pool_address` * **Limits:** Daily submission limit + fraud/quality validation. ### `POST /api/edit-agent` Update an agent you own (scoped by `user_id`). *(API key or session)* * **Body:** `id` (required) + any editable agent fields (name, agent, description, pricing, category, status, image, links, etc.) * **Returns:** `success`, `id`, `listing_url`, `updated_data` ### `GET /api/get-agents/[id]/full` Full agent content. `403` unless free / owner / purchased. * **Returns:** full agent data + `access_granted`, `access_reason` ### `GET /api/get-agents/fetch-agent-count` Count of the authenticated user's agents. *** ## Prompts ### `POST /api/add-prompt` Create a marketplace prompt; optional tokenization + image. *(API key or session)* * **Body:** `name`, `prompt`, `description`, `useCases[]`, `tags`, `is_free`, `price_usd`, `category`, `status`, `tokenized_on`, `ticker`, `image_url` / `image_base64` / `file_path`, `links[]`, `seller_wallet_address`, `payment_method`, `creator_wallet`, `private_key`, `fee_selection`, `vault_mode` * **Returns:** `success`, `id`, `listing_url`, `tokenized`, `token_address`, `pool_address` ### `POST /api/edit-prompt` Update a prompt you own. *(API key or session)* * **Body:** `id` (required) + editable prompt fields * **Returns:** `success`, `id`, `listing_url`, `updated_data` ### `GET /api/get-prompts/[id]/full` Full prompt content. `403` unless free / owner / purchased. Lookup by UUID or name. ### `GET /api/get-prompts/fetch-prompt-count` Count of the authenticated user's prompts. *** ## Bundles ### `POST /api/v1/publish/bundle` Publish a bundle — a curated collection of marketplace agents/prompts (by URL) and/or custom inline prompts. * **Body:** `name`, `description`, `items[]` (1–50, each either `{ url }` or `{ name, description, content }`), `tags`, `image_url` / `image_base64`, `links[]`, `business_model` * **Returns:** `success`, `id`, `listing_url`, `item_count` * **Notes:** Bundles are free to publish. Rate limit: 20 bundles/day per user. Duplicate names (same user) return `409`. <Card title="Full reference" icon="box" href="/docs/marketplace/bundles-api"> Bundles API — request/response details and code examples </Card> *** ## Token Launch ### `POST /api/token/launch` Launch a single tokenized agent (creates the agent + Solana token). Forwards your `Authorization` header to `add-agent`. * **Content types:** JSON or `multipart/form-data` (image upload) * **Body:** `name`, `description`, `ticker`, `private_key`, `image` (url / base64 / file), `fee_selection` (`frenzy` | `market`), `quote_mint` (`SOL` | `USDC`), `vault_mode` * **Returns:** `success`, `id`, `listing_url`, `tokenized`, `token_address`, `pool_address` * **Notes:** Requires ≥ \~0.04 SOL in the creator wallet. ### `POST /api/token/launch/batch` Launch up to 50 tokenized agents in parallel. JSON only. * **Body:** `private_key` (default, optional) + `tokens[] { name, description, ticker, private_key?, image?, fee_selection? }` * **Returns:** `success`, `total`, `succeeded`, `failed`, `results[]`, `failures[]` (`207` on partial success) *** ## Reviews ### `POST /api/reviews` Submit a review for an agent / prompt / tool (one per user per item). * **Body:** `model_id`, `model_type` (`agent` | `prompt` | `tool`), `rating` (1–5), `comment` * **Returns:** `success`, `review` (`409` if already reviewed) *** ## Endpoints at a glance | Method | Path | Resource | | -------- | ------------------------------------- | ------------ | | GET | `/api/product/list` | Products | | GET | `/api/product/fees` | Products | | POST | `/api/user-products` | Products | | GET/POST | `/api/get-tokenized-products` | Products | | POST | `/api/add-agent` | Agents | | POST | `/api/edit-agent` | Agents | | GET | `/api/get-agents/[id]/full` | Agents | | GET | `/api/get-agents/fetch-agent-count` | Agents | | POST | `/api/add-prompt` | Prompts | | POST | `/api/edit-prompt` | Prompts | | GET | `/api/get-prompts/[id]/full` | Prompts | | GET | `/api/get-prompts/fetch-prompt-count` | Prompts | | POST | `/api/v1/publish/bundle` | Bundles | | POST | `/api/token/launch` | Token Launch | | POST | `/api/token/launch/batch` | Token Launch | | POST | `/api/reviews` | Reviews | # Vault Mode Source: https://docs.swarms.ai/docs/marketplace/vault-mode Token-gate your tokenized agents and prompts so only $TICKER holders can view the full listing **Vault Mode** lets creators gate access to their tokenized agents and prompts behind token ownership. When enabled, the listing page is locked for anyone who doesn't hold the entity's token — and instantly unlocked the moment they do. It is the first native, token-gated distribution model for the Swarms Marketplace, turning every tokenized product into a holders-only experience. <Info> Vault Mode requires the entity to be **tokenized** first. Configure it from [swarms.world/launch](https://swarms.world/launch) by toggling **Tokenize → Vault Mode**. </Info> *** ## What is Vault Mode? When Vault Mode is enabled on a tokenized agent or prompt: * The full listing (system prompt, agent code, metadata, etc.) is **blurred and inaccessible** to non-holders. * Visitors see a **"Holders only"** gate with a built-in **Buy \$TICKER** widget. * Any **non-zero balance** of the entity's token unlocks the page. * The **creator always has access**, regardless of holder status. * Holder status is cached for **5 minutes** per wallet/token pair to keep the experience snappy. This unlocks an entirely new monetization model for the agent economy — token-gated agents, premium prompts, exclusive tools, private swarms, and member-only AI products. <CardGroup> <Card title="Token-Gated Access" icon="lock"> Only holders of your agent's token can view the system prompt, code, and metadata. </Card> <Card title="Built-In Buy Flow" icon="coins"> Non-holders see a one-click buy widget — they can become holders without leaving the page. </Card> <Card title="Automatic Permissions" icon="user-check"> Holder verification runs onchain. No allowlists, no manual approvals. </Card> <Card title="Creator Bypass" icon="shield-check"> The wallet that minted the agent always sees the unblurred listing. </Card> </CardGroup> *** ## Benefits Vault Mode creates a direct alignment between holders and creators: * **Token-gated access** to agents and prompts. * **New monetization models** beyond subscriptions — your token *is* the product key. * **Exclusive access** for token holders who back you early. * **Automated permission management** with no offchain bookkeeping. * **Premium AI products and experiences** that scale with your token's distribution. When a non-holder buys \$TICKER on the page, the gate animates into an **"Access granted"** confirmation and reveals the listing — no refresh required. *** ## How to enable Vault Mode <Steps> <Step title="Sign in or sign up"> Create or sign into your Swarms account at [swarms.world/signin](https://swarms.world/signin). </Step> <Step title="Open the Launchpad"> Go to [swarms.world/launch](https://swarms.world/launch) and start a new agent or prompt listing. Vault Mode is currently supported for **agents** and **prompts** (not tools). </Step> <Step title="Select Tokenize"> Fill in the required fields (name, description, image, etc.) and choose **Tokenize** as your monetization option. Vault Mode requires a tokenized product because the token is the access key. </Step> <Step title="Enable Vault Mode"> In the Tokenize panel, toggle **Vault Mode** on. You'll see a description confirming: > *Only token holders can view this agent.* </Step> <Step title="Launch"> Submit your listing. Once your token is minted, the page is automatically gated. Your wallet (the creator) sees it unblurred; everyone else must hold \$TICKER. </Step> </Steps> <Tip> Vault Mode can be combined with **Frenzy Mode** for tokenized agents and prompts. Holders unlock the listing, and every trade on the bonding curve collects 2× fees. See the [Frenzy Mode doc](/docs/marketplace/frenzy-mode). </Tip> *** ## How it works under the hood Vault Mode is a client-rendered gate backed by an onchain balance check. <Steps> <Step title="The listing renders, blurred"> The full entity page is rendered as a blurred, non-interactive layer underneath the gate. Nothing sensitive (system prompt, code, etc.) is shipped to the client for non-holders in plaintext that would otherwise be hidden — the gate is paired with a server-enforced check below. </Step> <Step title="The gate calls the holder endpoint"> Once the visitor's wallet is connected, the gate calls: ``` GET /api/vault-mode/check-holder?wallet={publicKey}&token_address={mint} ``` The endpoint returns: ```json theme={null} { "is_holder": true, "balance": 12500 } ``` </Step> <Step title="Holder cache (5-minute TTL)"> The result is cached in-memory and in `sessionStorage` under `vault-mode:holder:{wallet}:{mint}` for 5 minutes. Subsequent visits within that window skip the network round-trip. </Step> <Step title="Unlock animation"> When a holder is detected for the first time, the gate plays a brief **"Access granted"** → **reveal** animation, then renders the full listing. The creator and existing holders bypass the gate immediately. </Step> <Step title="In-gate buy flow"> Non-holders can buy \$TICKER directly from the gate without leaving the page: 1. Enter a SOL amount — a live quote estimates how much \$TICKER you'll receive. 2. Sign the swap in your wallet. 3. On success, the holder cache is invalidated and re-checked. 4. The page unlocks automatically with the **"Access granted"** animation. </Step> </Steps> *** ## Visual indicators A purple **VAULTED** tag with a lock icon appears next to the entity title on any gated listing, so visitors immediately understand the access model. If the entity is also in Frenzy Mode, the orange **FRENZY** tag renders alongside it. *** ## FAQ <AccordionGroup> <Accordion title="Can I enable Vault Mode without tokenizing?"> No. Vault Mode is the access mechanism for tokenized products — the token itself is the key. If you want a paid-but-not-tokenized listing, use the standard paid monetization option instead. </Accordion> <Accordion title="What's the minimum holding required?"> Any non-zero balance unlocks the listing. There is no minimum threshold today. </Accordion> <Accordion title="Does the creator need to hold the token?"> No. The wallet that launched the agent is recognized as the owner and always has unblurred access, even with a zero balance. </Accordion> <Accordion title="Can I change a listing from Vault Mode to public later?"> Yes. Edit the listing from your profile and toggle Vault Mode off. The change applies immediately. </Accordion> <Accordion title="What happens if a holder sells their tokens?"> They lose access on the next holder check (within 5 minutes, or immediately on hard refresh). The gate reappears with the buy widget. </Accordion> <Accordion title="Does Vault Mode work for tools?"> Not currently. Vault Mode is supported on **agents** and **prompts** because those are the entity types eligible for tokenization on the marketplace today. </Accordion> </AccordionGroup> *** ## See also * [Monetization Models](/docs/marketplace/tokenization) — Free, paid, and tokenized launch options. * [Frenzy Mode](/docs/marketplace/frenzy-mode) — 2× bonding curve fees and leaderboard placement. * [Self-Tokenizing Agents Tutorial](/docs/marketplace/launchpad-tokenize-your-agent-tutorial) — End-to-end tokenized launch walkthrough. * [Token Launch API](/docs/marketplace/token-launch-api) — Programmatic tokenized launches. # Yuki Marketplace Companion Source: https://docs.swarms.ai/docs/marketplace/yuki Learn how Yuki helps users navigate the Swarms Marketplace, understand products, and get live marketplace guidance. Yuki is the built-in AI support agent for the Swarms Marketplace. She appears throughout the marketplace experience so users can ask questions, understand listings, compare products, and find the right agents, prompts, or tools without leaving the page they are viewing. Yuki combines page awareness, product context, account context, and live marketplace data to provide timely guidance. Whether you are browsing as a guest, managing your dashboard, reviewing an agent listing, or exploring tokenized products, Yuki helps explain what you are seeing and points you to the next best action. *** ## Where Yuki Appears Yuki is present on the following pages: * Marketplace homepage * Individual agent, prompt, and tool pages * User profile pages * All platform dashboard pages (Dashboard, API Keys, Chat, Leaderboard, Account, Billing, History, Referral, Organization, Registry) * Launch and Support pages She does not appear on pages where she would not be relevant, such as legal pages or external routes. *** ## What Yuki Can See ### Your Current Page Yuki always knows which page you are on. A live label in the widget header shows the current page — for example, "Marketplace", "Dashboard", "API Keys", or a specific product name like "Agent: ResearchBot". This context is active in every conversation, so you never need to explain where you are or what you are looking at. ### Product Context When you are on an individual agent, prompt, or tool page, Yuki automatically loads the full details of that product, including: * Name and description * Tags and categories * Pricing and monetization model * Use cases * Dependencies and requirements * Creator username This means you can ask "does this agent support multi-step workflows?" or "what is this tool priced at?" and Yuki already has the answer — no copy-pasting required. ### Your Account Yuki knows your login state. If you are signed in, she has access to your username, full name, and email address so her guidance is personalized to your account. If you are browsing as a guest, she knows that too and adjusts her answers accordingly. ### The Full Site Map Yuki has a complete map of every page on swarms.world — public pages, platform pages, and external links. When you ask where something is or how to navigate to a feature, she returns the exact URL. ### Marketplace Categories Yuki knows the full category taxonomy used across agents, prompts, and tools. She can filter recommendations and rankings by category, including: Healthcare, Education, Finance, Research, Public Safety, Marketing, Sales, Customer Support, and more. If you are looking for something specific to an industry or use case, tell her and she will narrow the results accordingly. ### Live Marketplace Data Yuki has real-time read access to the Swarms Marketplace database. When a question requires current data, she queries the database directly and returns live results. She can surface: * Top-rated agents, prompts, and tools by rating * Best-selling products by total revenue from completed transactions * Highest-rated agents running Frenzy mode (dynamic, market-driven pricing) When Yuki is fetching live data, the widget shows a "Fetching marketplace data" indicator so you can see exactly when a live query is in progress. Results come back as ranked, linked lists reflecting the actual state of the marketplace at that moment. ### External Resources Yuki knows and can link you to all official Swarms resources: * Documentation: docs.swarms.world * GitHub: github.com/kyegomez/swarms * Discord community: discord.gg/EamjgSaEQf * Twitter / X: x.com/swarms\_corp * Book a demo: cal.com/swarms Ask her for any of these and she will give you the direct link. *** ## What Yuki Can Do **Answer product questions.** Ask anything about an agent, prompt, or tool you are currently viewing. Yuki has the full listing context and will give you a direct answer. **Find the right product.** Describe what you are trying to accomplish and Yuki will recommend agents, prompts, or tools that fit your workflow — filtered by category if needed. **Surface live rankings.** Ask for the highest-rated or best-selling products in any category and get a current, database-backed list. **Navigate the platform.** Ask where any feature is — API keys, billing, leaderboard, referral program, organization settings — and Yuki will give you the exact URL. **Explain how things work.** Credits, monetization models, tokenization, Frenzy pricing, publishing an agent — Yuki can walk you through any part of how the platform works. **Link to external resources.** Ask for the docs, GitHub repo, Discord, or demo booking link and she will provide it directly. **Support queries.** For issues that require human support, Yuki can direct you to the support page and help you frame your request. *** ## How Yuki Thinks Yuki is powered by Claude Sonnet with extended thinking enabled. Before responding, she reasons through your question internally — determining whether live data is needed, what context is relevant, and what the most useful answer looks like. For questions that require marketplace data, she fetches it in real time before generating a response. You can see her reasoning process. Each assistant message has a collapsible "Thinking" panel that shows the internal reasoning chain that produced the answer. It can be expanded or collapsed at any time. Responses stream in real time — text appears word by word as it is generated rather than arriving all at once. *** ## Copying Responses Every message Yuki sends has a copy button beneath it. Click it to copy the full response text to your clipboard. The button confirms the copy with a brief "Copied" indicator before returning to its default state. *** ## Conversation Persistence and Context Window Yuki remembers your conversation across the session. Navigating between pages, refreshing the browser, or switching tabs does not clear the thread. Your conversation history is stored locally in your browser with a stable conversation ID. **Context window:** Yuki sends the last 10 messages of your conversation to the model on each turn. In very long conversations, earlier messages will fall outside the active context and Yuki may not recall them. If you notice her losing track of something discussed much earlier, use the reset button to start a focused new thread. To start fresh at any point, use the reset button in the widget header. This clears the history and generates a new conversation ID. *** ## Full-Page Mode The maximize button in the widget header opens a full-page chat at `/yuki/chat` in a new tab. This is the same Yuki with the same context — just more screen space for longer conversations. *** ## Privacy Yuki's conversations are not stored on Swarms servers beyond what is needed to generate a response. Conversation history lives in your browser's local storage and is cleared when you reset the conversation or clear your browser data. Yuki does not have access to your payment information, private API keys, or any data outside of what is described in this document. *** ## Getting Started Open Yuki from the bottom right corner of any marketplace page. You do not need to configure anything or create an account. If you are logged in, she already knows who you are. If you are browsing as a guest, she is still fully functional. Start with a question about any product you are looking at, or ask her to find the best agent for a task you are working on. Link: [https://swarms.world](https://swarms.world) # Multi-Agent Best Practices Source: https://docs.swarms.ai/unused/best_practices Production-grade best practices for using the Swarms API effectively. Learn how to choose the right swarm architecture, optimize costs, and implement robust error handling. This comprehensive guide outlines production-grade best practices for using the Swarms API effectively. Learn how to choose the right swarm architecture, optimize costs, and implement robust error handling. ## Quick Reference Cards ### Swarm Types **Available Swarm Architectures** | Swarm Type | Best For | Use Cases | | --------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------- | | `AgentRearrange` | Dynamic workflows | • Complex task decomposition<br />• Adaptive processing<br />• Multi-stage analysis<br />• Dynamic resource allocation | | `MixtureOfAgents` | Diverse expertise | • Cross-domain problems<br />• Comprehensive analysis<br />• Multi-perspective tasks<br />• Research synthesis | | `BatchedGridWorkflow` | Data processing | • Financial analysis<br />• Data transformation<br />• Batch calculations<br />• Report generation | | `SequentialWorkflow` | Linear processes | • Document processing<br />• Step-by-step analysis<br />• Quality control<br />• Content pipeline | | `ConcurrentWorkflow` | Parallel tasks | • Batch processing<br />• Independent analyses<br />• High-throughput needs<br />• Multi-market analysis | | `GroupChat` | Collaborative solving | • Brainstorming<br />• Decision making<br />• Problem solving<br />• Strategy development | | `MultiAgentRouter` | Task distribution | • Load balancing<br />• Specialized processing<br />• Resource optimization<br />• Service routing | | `HierarchicalSwarm` | Complex organization | • Project management<br />• Research analysis<br />• Enterprise workflows<br />• Team automation | | `MajorityVoting` | Consensus needs | • Quality assurance<br />• Decision validation<br />• Risk assessment<br />• Content moderation | | `DebateWithJudge` | Adversarial review | • Contested decisions<br />• Red-teaming<br />• Argument stress-testing | | `HeavySwarm` | Deep multi-pass analysis | • High-stakes research<br />• Exhaustive due diligence | | `RoundRobin` | Even task rotation | • Fair load distribution<br />• Sequential specialist review | See [Available Architectures](/docs/documentation/multi-agent/available-architectures) for the full, current list of swarm types. ### Application Patterns **Specialized Application Configurations** | Application | Recommended Swarm | Benefits | | --------------------- | -------------------- | ---------------------------------------------------------------------------------------------- | | **Team Automation** | `HierarchicalSwarm` | • Automated team coordination<br />• Clear responsibility chain<br />• Scalable team structure | | **Research Pipeline** | `SequentialWorkflow` | • Structured research process<br />• Quality control at each stage<br />• Comprehensive output | | **Trading System** | `ConcurrentWorkflow` | • Multi-market coverage<br />• Real-time analysis<br />• Risk distribution | | **Content Factory** | `MixtureOfAgents` | • Automated content creation<br />• Consistent quality<br />• High throughput | ### Cost Optimization **Advanced Cost Management Strategies** | Strategy | Implementation | Impact | | ------------------ | ------------------------------ | ------------------------------------------- | | Batch Processing | Group related tasks | 20-30% cost reduction | | Off-peak Usage | Schedule for 8 PM - 6 AM PT | 50% cost reduction (Swarm Completions only) | | Token Optimization | Precise prompts, focused tasks | 10-20% cost reduction | | Caching | Store reusable results | 30-40% cost reduction | | Agent Optimization | Use minimum required agents | 15-25% cost reduction | | Smart Routing | Route to specialized agents | 10-15% cost reduction | | Prompt Engineering | Optimize input tokens | 15-20% cost reduction | ### Service Tiers **Choosing the Right Service Tier** | Tier | Best For | Benefits | Considerations | | ---------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------ | | Standard | • Real-time processing<br />• Time-sensitive tasks<br />• Critical workflows | • Immediate execution<br />• Higher priority<br />• Predictable timing | • Higher cost<br />• 5-min timeout | | Off-peak (Swarm Completions) | • Batch processing<br />• Non-urgent tasks<br />• Cost-sensitive workloads | • 50% cost reduction on tokens<br />• 8 PM - 6 AM PT | • Only applies to Swarm Completions<br />• Time window restriction | ### Industry Solutions **Industry-Specific Swarm Patterns** | Industry | Use Case | Applications | | -------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------- | | **Finance** | Automated trading desk | • Portfolio management<br />• Risk assessment<br />• Market analysis<br />• Trading execution | | **Healthcare** | Clinical workflow automation | • Patient analysis<br />• Diagnostic support<br />• Treatment planning<br />• Follow-up care | | **Legal** | Legal document processing | • Document review<br />• Case analysis<br />• Contract review<br />• Compliance checks | | **E-commerce** | E-commerce operations | • Product management<br />• Pricing optimization<br />• Customer support<br />• Inventory management | ### Error Handling **Advanced Error Management Strategies** | Error Code | Strategy | Recovery Pattern | | ---------- | ----------------- | -------------------------------------- | | 400 | Input Validation | Pre-request validation with fallback | | 401 | Auth Management | Secure key rotation and storage | | 429 | Rate Limiting | Exponential backoff with queuing | | 500 | Resilience | Retry with circuit breaking | | 503 | High Availability | Multi-region redundancy | | 504 | Timeout Handling | Adaptive timeouts with partial results | ## Choosing the Right Swarm Architecture ### Decision Framework Use this framework to select the optimal swarm architecture for your use case: 1. **Task Complexity Analysis** * Complex tasks → `HierarchicalSwarm` or `MultiAgentRouter` * Dynamic tasks → `AgentRearrange` 2. **Workflow Pattern** * Linear processes → `SequentialWorkflow` * Parallel operations → `ConcurrentWorkflow` * Collaborative tasks → `GroupChat` 3. **Domain Requirements** * Multi-domain expertise → `MixtureOfAgents` * Data processing → `BatchedGridWorkflow` * Quality assurance → `MajorityVoting` ### Industry-Specific Recommendations #### Finance **Financial Applications** * Risk Analysis: `HierarchicalSwarm` * Market Research: `MixtureOfAgents` * Trading Strategies: `ConcurrentWorkflow` * Portfolio Management: `BatchedGridWorkflow` #### Healthcare **Healthcare Applications** * Patient Analysis: `SequentialWorkflow` * Research Review: `MajorityVoting` * Treatment Planning: `GroupChat` * Medical Records: `MultiAgentRouter` #### Legal **Legal Applications** * Document Review: `SequentialWorkflow` * Case Analysis: `MixtureOfAgents` * Compliance Check: `HierarchicalSwarm` * Contract Analysis: `ConcurrentWorkflow` ## Production Best Practices ### Best Practices Summary **Recommended Patterns** * Use appropriate swarm types for tasks * Implement robust error handling * Monitor and log executions * Cache repeated results * Rotate API keys regularly * Choose appropriate service tier based on task urgency * Schedule non-urgent tasks during off-peak hours (8 PM - 6 AM PT) for Swarm Completions to benefit from night-time discount **Anti-patterns to Avoid** * Hardcoding API keys * Ignoring rate limits * Missing error handling * Excessive agent count * Inadequate monitoring * Not implementing retry logic for failed requests ### Performance Benchmarks **Typical Performance Metrics** | Metric | Target Range | Warning Threshold | | -------------- | ------------ | ----------------- | | Response Time | \< 2s | > 5s | | Success Rate | > 99% | \< 95% | | Cost per Task | \< \$0.05 | > \$0.10 | | Cache Hit Rate | > 80% | \< 60% | | Error Rate | \< 1% | > 5% | | Retry Rate | \< 10% | > 30% | ### Additional Resources **Useful Links** * [API Dashboard](https://swarms.world/platform/api-keys) # Cost Optimization: Mixing Models for 5x Savings Source: https://docs.swarms.ai/unused/cost-optimization A strategic guide to cutting Swarms API spend by tiering models, gating expensive agents behind cheap classifiers, batching overnight for the 50% night-mode discount, and capping the only two settings that actually move the bill. ## What This Guide Covers * Why one-size-fits-all model selection is the wrong default for any production swarm * Four concrete cost patterns you can drop into existing pipelines without re-architecting * The 50% night-mode discount window on swarm completions and how to claim it * A reproducible cost table comparing naive (all-flagship) to a tiered + batch + night-mode setup * The two configuration levers (`max_tokens` and `max_loops`) that quietly drive most of your spend <Info> The goal of this guide is not to make your agents cheaper at the expense of quality. It is to put your most expensive model only where it changes the answer — and to use cheaper models, batch endpoints, and the night-mode window everywhere else. </Info> ## Why This Matters Most production Swarms bills look the same when you trace them: one or two agents do work that genuinely requires a flagship model (synthesis, hard reasoning, final write-up) and three or four agents do work a cheaper model would handle identically (classification, extraction, formatting, routing). Running every agent on the flagship is the default — and the default is wrong. The job to be done is not "use the best model." It is "produce a defensible artifact at the lowest cost-per-unit-of-quality." The patterns below are the levers that move that ratio, in priority order. ## The Cost-Capability Trade-Off Anthropic and OpenAI both publish three rough tiers, and the ratios are roughly the same across providers: | Tier | Anthropic | OpenAI | Use For | | -------- | --------------------------- | ------------------------------ | ------------------------------------------------------------------------------- | | Cheap | Haiku family | `gpt-4.1-mini`, `gpt-4.1-mini` | Triage, classification, extraction, routing, formatting | | Mid | Sonnet family | `gpt-4.1`, `gpt-4.1` | Most analysis, most worker agents, drafts | | Flagship | `anthropic/claude-opus-4-8` | (top OpenAI reasoning tier) | Synthesis, final judgments, multi-step reasoning, the agent that signs the memo | As a rule of thumb across providers, cheap-tier input is roughly an order of magnitude cheaper than flagship input, and cheap-tier output is several times cheaper than flagship output. Exact ratios shift with each release — but the gap is always wide enough that misallocating tiers is the single biggest unforced error in production swarms. The mental model: **default to mid-tier for workers, drop to cheap-tier for anything that classifies or extracts, promote to flagship only where the answer changes.** ## Pattern 1: Tiered Models in a Single Swarm In a `HierarchicalSwarm`, the director synthesizes — that's the agent that benefits from a flagship model. The workers each own a narrow lane and rarely need the same horsepower. Mix tiers in one swarm config: ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} payload = { "name": "Tiered Hierarchical Swarm", "description": "Flagship director, cheap-tier workers.", "swarm_type": "HierarchicalSwarm", "max_loops": 1, "task": ( "Produce an investment brief on the semiconductor sector: " "key catalysts, top three risks, and a one-line outlook." ), "agents": [ { "agent_name": "Director", "description": "Synthesizes worker output into the final brief.", "system_prompt": ( "You are the director. You do NOT redo the workers' " "research. You reconcile, decide, and produce one clean " "structured brief." ), "model_name": "anthropic/claude-opus-4-8", "role": "coordinator", "max_loops": 1, "max_tokens": 4096, # Note: temperature intentionally omitted for Opus 4.8 }, { "agent_name": "Catalysts Worker", "description": "Lists the near-term sector catalysts.", "system_prompt": ( "List the three most important near-term catalysts for " "the semiconductor sector. One sentence each." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.3, }, { "agent_name": "Risks Worker", "description": "Lists the top sector risks.", "system_prompt": ( "List the three most important risks to the semiconductor " "sector over the next two quarters. One sentence each." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 1024, "temperature": 0.3, }, { "agent_name": "Outlook Worker", "description": "Drafts a one-line outlook for the director to refine.", "system_prompt": ( "Write a single one-line outlook for the semiconductor " "sector over the next two quarters." ), "model_name": "gpt-4.1-mini", "role": "worker", "max_loops": 1, "max_tokens": 256, "temperature": 0.3, }, ], } response = requests.post( f"{BASE_URL}/v1/swarm/completions", headers=headers, json=payload, timeout=300, ) print(json.dumps(response.json(), indent=2)) ``` The workers do bounded, low-creativity research at cheap-tier prices. The director gets the flagship model where its synthesis ability actually matters. Three cheap workers + one flagship director usually beats four flagship agents on both cost and quality, because the cheap workers are forced to stay narrow. <Note> When the flagship in the config is `anthropic/claude-opus-4-8`, do not set `temperature`. See [Claude Opus 4.8](/docs/examples/examples/claude-opus-4-8) for the full rationale — Anthropic's API will reject the request if `temperature` is supplied. </Note> ## Pattern 2: Two-Pass Filtering Most production workloads are heavily skewed: 70-90% of incoming items don't need the expensive analyst. A cheap classifier agent decides whether the expensive one runs at all. This is the highest-ROI pattern in this guide for any high-volume queue (support tickets, claim triage, document review, lead scoring). ```python theme={null} import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} def classify(item_text: str) -> str: """Cheap classifier. Returns 'escalate' or 'auto-resolve'.""" payload = { "agent_config": { "agent_name": "Triage Classifier", "description": "Decides if an item needs an expensive analyst.", "system_prompt": ( "You are a triage classifier. Read the item and answer with " "exactly one word: 'escalate' if it requires expert analysis " "(novel issue, regulatory risk, dollar amount over $10k, " "VIP customer) or 'auto-resolve' if it is routine. " "Output one word only." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "max_tokens": 8, "temperature": 0.0, }, "task": item_text, } r = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=60, ) return r.json().get("outputs", "").strip().lower() def expensive_analyst(item_text: str) -> dict: """Expensive flagship analyst. Only runs on escalated items.""" payload = { "agent_config": { "agent_name": "Senior Analyst", "description": "Deep analysis for escalated items only.", "system_prompt": ( "You are a senior analyst. Produce a structured analysis " "with: summary, key risks, recommended action, and " "uncertainty notes." ), "model_name": "anthropic/claude-opus-4-8", "max_loops": 1, "max_tokens": 4096, }, "task": item_text, } r = requests.post( f"{BASE_URL}/v1/agent/completions", headers=headers, json=payload, timeout=300, ) return r.json() def process(item_text: str) -> dict: decision = classify(item_text) if "escalate" in decision: return {"path": "expensive", "result": expensive_analyst(item_text)} return {"path": "cheap", "result": {"decision": "auto-resolve"}} ``` If 80% of items auto-resolve at cheap-tier prices and only 20% reach the flagship, your effective cost-per-item collapses by roughly 4x against a naive "everything goes to the flagship" setup — without sacrificing quality on the items that mattered. ## Pattern 3: Batch Endpoints + Night Mode The Swarms platform applies a **50% night-time discount** on input and output token costs for swarm completions processed between **8 PM and 6 AM Pacific** (`America/Los_Angeles`). The discount is implemented in `calculate_swarm_cost` — see `api/swarm_completions.py` — and applies to billed swarm token costs (the per-agent fixed component is unaffected; agent completions are not discounted). The platform decides the discount based on the server clock when the work is processed, so the way you capture it is to **send the work during that window**, typically via the batch endpoints. Two endpoints matter here: * `/v1/agent/batch/completions` — array of single-agent jobs in one request (batching only; the night discount does not apply to agent completions) * `/v1/swarm/batch/completions` — array of multi-agent swarm jobs in one request (night discount applies) The shape is the same: each item is a full request body, identical to what you'd send to the non-batch endpoint. ```python theme={null} import json import os import requests from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("SWARMS_API_KEY") BASE_URL = "https://api.swarms.world" headers = {"x-api-key": API_KEY, "Content-Type": "application/json"} # Build a queue of single-agent jobs to run overnight. agent_batch = [ { "agent_config": { "agent_name": "Earnings Summarizer", "description": "One-paragraph earnings summary.", "system_prompt": ( "Summarize the company's latest quarter in one paragraph. " "Include revenue YoY, EPS, and one forward-looking item." ), "model_name": "gpt-4.1-mini", "max_loops": 1, "max_tokens": 512, "temperature": 0.2, }, "task": f"Summarize {ticker} most recent earnings release.", } for ticker in ["AAPL", "MSFT", "NVDA", "META", "AMZN", "GOOGL"] ] response = requests.post( f"{BASE_URL}/v1/agent/batch/completions", headers=headers, json=agent_batch, timeout=600, ) results = response.json() for item in results: print(item) ``` To actually claim the discount, schedule the job. A simple `cron` entry on a Pacific-time host is enough; for cloud schedulers, anchor on `America/Los_Angeles` and fire any time between 8 PM and 6 AM: ```cron theme={null} # Run nightly batch at 9:00 PM Pacific 0 21 * * * /usr/bin/python3 /opt/jobs/run_overnight_batch.py ``` <Info> Night-mode is a 50% discount on **swarm-completion token costs**, not on the per-agent base charge. For token-heavy swarms (long inputs, long outputs) it cuts the bill roughly in half. For very short calls dominated by the per-agent fixed cost, the effective savings is smaller. Larger jobs benefit more. </Info> ## Pattern 4: Cap Tokens and Loops `max_tokens` and `max_loops` are the most direct, least glamorous, most effective levers in your config. Most production swarms ship with both set carelessly high "just in case." That's where the silent spend hides. Conservative defaults that work in production: | Agent role | `max_tokens` | `max_loops` | Notes | | ------------------------------ | ------------ | ----------- | ------------------------------------------------------- | | Classifier / triage | 16 - 64 | 1 | One-word or short-label outputs | | Extraction (fields from a doc) | 512 - 1024 | 1 | Structured output, bounded | | Worker doing one analysis lane | 2048 - 4096 | 1 | Most swarm workers live here | | Synthesizer / director | 4096 - 8192 | 1 - 2 | Only raise loops if the task is genuinely iterative | | Long-form research memo | 8192 | 1 | Higher is rarely the right answer; chain agents instead | **The two rules**: 1. **Default `max_loops` to 1.** Raise it only when you have evidence a single pass underperforms. Each additional loop multiplies cost roughly linearly and helps less than chaining a fresh agent. 2. **Set `max_tokens` close to what the agent should actually produce.** A classifier with `max_tokens=4096` is paying for headroom it will never use, plus the long-tail risk of the model going long. Bound it. ## Real-World Numbers Take a realistic production workload: an investment-research team running 500 single-agent summaries plus 50 multi-agent deep-dive swarms per day. The naive setup runs everything on a flagship model, in the middle of the business day, with generous `max_tokens` and `max_loops`. The optimized setup applies all four patterns above. Assume rough per-million-token costs of flagship \~\$15 input / \$75 output, mid-tier \~\$3 input / \$15 output, cheap \~\$0.30 input / \$1.20 output. (Use these for relative scale; check your provider's published rates for current values.) | Workload | Naive (all flagship, peak hours) | Optimized (tiered + batch + night) | | -------------------------------------------------------------- | -------------------------------- | --------------------------------------------------------------------- | | 500 single-agent summaries × \~600 input / \~300 output tokens | \~\$15.75/day | Cheap-tier + night mode: \~\$0.36/day | | 50 deep-dive swarms × 4 agents × \~2k input / \~1.5k output | \~\$28.50/day | Director-only flagship, workers cheap, batched at night: \~\$5.10/day | | **Total daily** | **\~\$44.25** | **\~\$5.46** | | **Effective multiplier** | — | **\~8x cheaper** | The savings come from four stacked decisions: (1) the 80% of work that didn't need a flagship model didn't get one, (2) the workers in the swarm dropped from flagship to cheap-tier, (3) `max_tokens` was set close to the actual output length, and (4) the whole pipeline ran during the night-mode window. Any one of them in isolation saves money. Stacked, they consistently produce a 5-10x reduction on real workloads. <Warning> These numbers are illustrative. Your actual ratio depends on the cheap-tier hit rate of your classifier (Pattern 2), the input/output mix of your specific prompts, and current published provider rates. Treat the table as the right shape, not the right absolute number, and measure your own workload. </Warning> ## A Checklist Before You Ship Run this list against any swarm config heading to production: * Does every agent need the model it's currently using? Demote any worker whose job is classification, extraction, or formatting. * Is `max_tokens` bounded close to the expected output length on every agent? * Is `max_loops` set to 1 unless you have measured that more loops change the answer? * Could a cheap classifier filter the queue before the expensive agent runs (Pattern 2)? * Can the workload run overnight on `/v1/swarm/completions` or `/v1/swarm/batch/completions` for the 50% night discount (Pattern 3)? * Have you confirmed the flagship agent is reserved for the role that genuinely benefits — synthesis, final judgment, the agent whose output is the artifact? ## Next Steps * Scale single-agent workloads with [Batch Agent Completions](/docs/examples/examples/batch-agent-scale-tutorial) * Run many swarms in one request with [Batch Swarm Completions](/docs/examples/examples/batch-swarm-scale-tutorial) * See the tiered hierarchical pattern end-to-end in the [Hierarchical Workflow Example](/docs/examples/examples/hierarchical-workflow) # Multi-Agent Swarm Types Source: https://docs.swarms.ai/unused/swarm_types Overview of all available multi-agent architectures in the Swarms API, each designed for specific use cases and workflows Each multi-agent architecture type is designed for specific use cases and can be combined to create powerful multi-agent systems. Below is an overview of all multi-agent pages with full links: | Item | Description | Link | | ----------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------- | | Multi-Agent | Landing page for multi-agent concepts and structures. | [Learn More](/docs/documentation/multi-agent/overview) | | Available architectures | Full, current list of all 16 supported swarm types. | [Learn More](/docs/documentation/multi-agent/available-architectures) | | Best practices | Design patterns and best practices for multi-agent systems. | [Learn More](/docs/documentation/multi-agent/best_practices) | | Sequential workflow | Executes tasks in a strict, predefined order. | [Learn More](/docs/documentation/multi-agent/sequential_workflow) | | Concurrent workflow | Runs independent tasks in parallel for higher throughput. | [Learn More](/docs/documentation/multi-agent/concurrent_workflow) | | Multi agent router | Intelligent dispatcher that routes tasks based on capabilities/load. | [Learn More](/docs/documentation/multi-agent/multi_agent_router) | | Mixture of agents | Combine diverse specialist agents for complex tasks. | [Learn More](/docs/documentation/multi-agent/mixture_of_agents) | | Group chat | Multi-agent collaborative discussion toward a shared goal. | [Learn More](/docs/documentation/multi-agent/group_chat) | | Majority voting | Consensus-based decision-making across multiple agents. | [Learn More](/docs/documentation/multi-agent/majority_voting) | | Hierarchical swarm | Multi-level structures with delegation and escalation. | [Learn More](/docs/documentation/multi-agent/hierarchical_swarm) | | Agent rearrange | Dynamically reorganize agents to optimize task performance. | [Learn More](/docs/documentation/multi-agent/agent_rearrange) | | Graph workflow | DAG-based execution with explicit node/edge dependencies. | [Learn More](/docs/documentation/multi-agent/graph_workflow) | | Debate with judge | Adversarial debate between agents, arbitrated by a judge agent. | [Learn More](/docs/documentation/multi-agent/debate_with_judge) | | Heavy swarm | Deep, multi-pass analysis for high-stakes tasks. | [Learn More](/docs/documentation/multi-agent/heavy_swarm) | | Round robin | Rotates the task evenly across all agents in sequence. | [Learn More](/docs/documentation/multi-agent/round_robin) | | Batched Grid Workflow | Execute multiple tasks across multiple agents in a grid pattern. | [Learn More](/docs/documentation/multi-agent/batched_grid_workflow) |