{"_id":"@calebrussel77/swarm","_rev":"2-1308bd17fc29182a685f366f9e8cac98","name":"@calebrussel77/swarm","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.1":{"name":"@calebrussel77/swarm","version":"0.1.1","keywords":["swarm","ai","LLM","vercel","agent","agents","orchestration","multi-agent","bun"],"author":{"name":"Caleb Russell","email":"calebrussel77@gmail.com"},"license":"MIT","_id":"@calebrussel77/swarm@0.1.1","maintainers":[{"name":"calebrussel77","email":"calebrussel77@gmail.com"}],"homepage":"https://github.com/calebrussel77/swarm#readme","bugs":{"url":"https://github.com/calebrussel77/swarm/issues"},"dist":{"shasum":"d5ee38d4ee6a844f1cd42f1b239148ac036116e5","tarball":"https://registry.npmjs.org/@calebrussel77/swarm/-/swarm-0.1.1.tgz","fileCount":15,"integrity":"sha512-FThw/0tUMBqatxMwAasGKHG5oCn81f3S0Y/DmxNIiNBnRinlKeKMTHaJpxznBUvFxAvXVCrjfzPeOKj7yQhnyg==","signatures":[{"sig":"MEUCIQCVwWJq/BJazooFqP3eG4dOJL9SUT1ZgPzJwY0KywzENQIgCCyRQ8jQ5OJ7A60ug9UqyQ+bvi+KgOfBdejFFBGmzOc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1494967},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"gitHead":"7272e3a1c0ec10c90f9f67618241859d7cd97c8e","private":false,"scripts":{"test":"bun test --timeout 20000 --coverage","build":"bun run build.ts && bunx tsc --emitDeclarationOnly --outDir dist","prepublishOnly":"bun run build"},"_npmUser":{"name":"calebrussel77","actor":{"name":"calebrussel77","type":"user","email":"calebrussel77@gmail.com"},"email":"calebrussel77@gmail.com"},"repository":{"url":"git+https://github.com/calebrussel77/swarm.git","type":"git"},"_npmVersion":"10.8.2","description":"LLM-agnostic typescript framework for creating OpenAI-style Swarm agents with the Vercel AI SDK","directories":{},"_nodeVersion":"20.18.1","dependencies":{"ai":"^4.3.16","zod":"^3.24.1","dotenv":"^16.4.7","nunjucks":"^3.2.4","@ai-sdk/google":"^1.2.19","@ai-sdk/openai":"^1.3.22","@openrouter/ai-sdk-provider":"^0.7.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"readline":"^1.3.0","@types/bun":"latest","typescript":"^5.0.0","@types/nunjucks":"^3.2.6"},"peerDependencies":{"typescript":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/swarm_0.1.1_1750263934079_0.23139717930812487","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@calebrussel77/swarm","version":"0.1.2","description":"LLM-agnostic typescript framework for creating OpenAI-style Swarm agents with the Vercel AI SDK","private":false,"publishConfig":{"access":"public"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"scripts":{"build":"bun run build.ts && bunx tsc --emitDeclarationOnly --outDir dist","test":"bun test --timeout 20000 --coverage","prepublishOnly":"bun run build"},"keywords":["swarm","ai","LLM","vercel","agent","agents","orchestration","multi-agent","bun"],"license":"MIT","homepage":"https://github.com/calebrussel77/swarm#readme","repository":{"type":"git","url":"git+https://github.com/calebrussel77/swarm.git"},"bugs":{"url":"https://github.com/calebrussel77/swarm/issues"},"author":{"name":"Caleb Russell","email":"calebrussel77@gmail.com"},"devDependencies":{"@types/bun":"latest","@types/nunjucks":"^3.2.6","readline":"^1.3.0","typescript":"^5.0.0"},"peerDependencies":{"typescript":"^5.0.0"},"dependencies":{"@ai-sdk/google":"^1.2.19","@ai-sdk/openai":"^1.3.22","@openrouter/ai-sdk-provider":"^0.7.2","ai":"^4.3.16","dotenv":"^16.4.7","nunjucks":"^3.2.4","zod":"^3.24.1"},"_id":"@calebrussel77/swarm@0.1.2","gitHead":"7867b200ea03c6f95a3fecdb6701edf7212ceb32","_nodeVersion":"20.18.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-F8r2+uDGSf1mNjEqP9g2ieN3Iz3ryeUx6D93/T0vZU3sgSk7XJ6tShii174TeaHKNWrWgucgMFHowkVOLaU5lQ==","shasum":"cbcf8c8274856b1cf5bc09f895cd3cf5e1dd07dc","tarball":"https://registry.npmjs.org/@calebrussel77/swarm/-/swarm-0.1.2.tgz","fileCount":15,"unpackedSize":1501975,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBsNZZeKQ/FsFEXyQQYCqRT/fHOtZA8K/FwjmnNOWbIvAiBlcBKHJPtHg+qpQ32yHS5/obWTe1fKOeyl6rDG5QtUcA=="}]},"_npmUser":{"name":"calebrussel77","email":"calebrussel77@gmail.com","actor":{"name":"calebrussel77","email":"calebrussel77@gmail.com","type":"user"}},"directories":{},"maintainers":[{"name":"calebrussel77","email":"calebrussel77@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/swarm_0.1.2_1750267319898_0.9583223409200017"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-18T16:25:34.016Z","modified":"2025-06-18T17:22:00.388Z","0.1.1":"2025-06-18T16:25:34.342Z","0.1.2":"2025-06-18T17:22:00.182Z"},"bugs":{"url":"https://github.com/calebrussel77/swarm/issues"},"author":{"name":"Caleb Russell","email":"calebrussel77@gmail.com"},"license":"MIT","homepage":"https://github.com/calebrussel77/swarm#readme","keywords":["swarm","ai","LLM","vercel","agent","agents","orchestration","multi-agent","bun"],"repository":{"type":"git","url":"git+https://github.com/calebrussel77/swarm.git"},"description":"LLM-agnostic typescript framework for creating OpenAI-style Swarm agents with the Vercel AI SDK","maintainers":[{"name":"calebrussel77","email":"calebrussel77@gmail.com"}],"readme":"# Swarm 🐝🐝🐝 \r\n\r\nSwarm is a powerful, flexible, and model-agnostic library for creating and managing multi-agent AI systems. It allows \r\nyou to create swarms of AI agents that can collaborate, hand off tasks, and maintain shared context.\r\n\r\nThis package is loosely based off of [OpenAI Swarm](https://github.com/openai/swarm), but please note that APIs are not \r\nidentical, and they are not intended to be. This package is intended to provide the same functionality, \r\nbut with better patterns, additional features, and modifications that fix some of the inherent \r\nissues with OpenAI's design. More about this in the [key concepts](#key-concepts) section below.\r\n\r\nThis library is _not_ opinionated about the LLM that you use. Since it is built on top of the \r\n[Vercel AI SDK](https://sdk.vercel.ai), it allows you to use any LLM or LLMs that you want. \r\n\r\nOne of the design concerns for this library is optimizing for low latency in realtime multimodal applications, e.g. \r\n[Pipecat](https://www.pipecat.ai/) applications and other multimodal, multi-component applications. \r\nThis library is _not_ strongly opinionated for such applications, but many defaults reflect the philosophy that statefulness is a reality and therefore a useful default for LLM applications, and LLM latency is a critical concern for user-facing apps\r\n\r\n# Table of Contents\r\n\r\n1. [Installation](#installation)\r\n2. [Key Concepts](#key-concepts)\r\n3. [Usage](#usage)\r\n4. [API Reference](#api-reference)\r\n5. [Examples](#examples)\r\n6. [Changelog](#changelog)\r\n\r\n\r\n# Installation\r\n\r\n```bash\r\nnpm install @calebrussel77/swarm\r\n```\r\n\r\n**Note**: This package requires `ai` version 4.3.16 or higher for proper `useChat` compatibility.\r\n\r\n# Key Concepts\r\n- **Agent**: An individual AI entity with specific capabilities and instructions. Each agent has a unique system prompt \r\nor prompt template and a set of tools. \r\n- **Swarm**: A collection of agents working together to accomplish tasks.\r\n- **Hive**: A factory for creating swarms with shared configuration.\r\n- **Context**: Shared information that can be updated and accessed by agents within a swarm. \r\n- **Handover**: Transferring control from one agent to another; achieved by a tool call.\r\n\r\n## Agents\r\nAgents are defined using the `Agent` class. By design, agents are stateless. \r\nEach agent has a name, a description, and a set of tools. An agent also have additional configuration \r\nproperties such as a `LanguageModel` to use that's different from the swarm's default, for example if you need a \r\nsmarter, faster, or more specialized LLM for a given task. \r\n\r\nEach agent's `instructions` should either be a string, a nunjucks template string that receives the swarm's context, or a function that receives the\r\ncontext object for the swarm and returns a string. This creates a reasonable amount of flexibility for your agent's \r\nprompt, but doesn't force you into patterns that you may not need.\r\n\r\n## Swarm\r\nUnlike an agent, a `Swarm` is stateful by default. This is _divergent from OpenAI's pattern_, but is useful in a variety\r\nof cases, including in realtime applications (e.g. voice) or situations where low latency is critical. For example, once\r\na response is generated and presented to a user (e.g. asking for feedback or more info for a tool call),\r\nthe last-active agent remains active. Once additional user input is received, the new user input can be passed to the \r\nswarm without incurring additional unnecessary handovers.  \r\n\r\nWhile stateful behavior is the default, it can be avoided by passing in a new list of messages and the agent to \r\nactivate as the entrypoint with each invocation. More information on this will be provided in the API documentation.\r\n\r\nEach hive and each swarm has a `queen`. Technically speaking, the queen is just the entrypoint to the swarm, or the \r\nfirst agent that will be executed. It may never need to be executed again depending on your swarm's structure, but for\r\nmany use-cases the `queen` will end up functioning as a type of orchestrator or router agent that handles dispatching \r\nother agents, processing their input, and \"managing\" the swarm, hence the name.\r\n\r\n\r\nEach swarm has a `context` object which provides a type of global state across invocations. \r\nAgents in the swarm can update the context with tool calls and handovers, and the swarm's context is passed in as a\r\ntemplate to each agent's instructions during rendering with each swarm invocation.\r\n\r\n> [!IMPORTANT]\r\n> When `generateText` or `streamText` are used, the swarm will generate and process tool calls and handovers until a text\r\n> response is generated.\r\n\r\nMultiple subsequent tool calls and handovers in a row can create latency before any text is generated for the user. \r\n\r\n> [!TIP]\r\n> When `streamText` is used, the name of the tool that is called as well as the agent calling it will be available in \r\n> the stream. Use this to provide feedback to users.\r\n\r\nThough streaming is more difficult to handle on the client side, it can allow you to\r\nprovide user feedback or take actions as new information becomes available, creating less latency, better UX, and \r\nlower time-to-interactivity.\r\n\r\n## Hive \r\nA `Hive` can be thought of as a stateless factory for creating swarms (which are stateful-by-default). For applications \r\nwhich use swarms statelessly, hives are unnecessary.\r\n\r\n## Handover \r\nA handover is when one agent in the swarm transfers control of execution to another agent. handovers are achieved through\r\nspecial tool calls that return another agent. Like traditional tool calls, a handover tool call can still have execution \r\nlogic; and both regular and handover tool calls can update the swarm's `context` object.\r\n\r\n## Hallucinations\r\nOpenAI's swarm framework is described as an educational tool, rather than a production-ready framework. One of the \r\nreasons for this is because the entire conversation history across handovers, including tools and tool results is \r\navailable to each agent, and LLMs are in-context learners.\r\n\r\nBecause the currently-executing can see messages in the conversation historyfrom other agents which are unrelated to \r\ntheir role, they can get confused and start to blend roles. \r\nAdditionally, swarm's design is prone to tool hallucination because the currently-executing agent can see tool calls \r\nfrom all the other agents, even for tools which are not available to it.\r\n\r\nThis framework provides several options and patterns to avoid these issues. \r\n# Usage\r\n\r\n## Creating an Agent\r\n\r\n```typescript\r\nimport { Agent } from 'agentswarm';\r\nimport { anthropic } from '@ai-sdk/anthropic';\r\n\r\nconst salesAgent = new Agent<SalesContext>({\r\n    name: 'Sales Agent',\r\n    description: 'Handles sales-related queries',\r\n    instructions: 'You are a sales representative for our company responsible for selling...',\r\n    tools: {\r\n        // Define tools here\r\n    },\r\n    model: anthropic('claude-3-haiku'), // overrides the Hive's default model for this agent\r\n});\r\n```\r\n\r\n## Creating a Hive\r\n\r\n```typescript\r\nimport { Hive } from 'agentswarm';\r\nimport { openai } from '@ai-sdk/openai';\r\n\r\ninterface SalesContext {\r\n    topic: string | null \r\n    weather: string | null\r\n}\r\n\r\nconst hive = new Hive<SalesContext>({\r\n  queen: receptionistAgent, // \"entrypoint\" to the swarm; often the \"orchestrator\"\r\n  defaultModel: openai('gpt-4o-mini'), // for agents that don't specify a model\r\n  defaultContext: { topic: null, weather: null },\r\n});\r\n```\r\n\r\n## Spawning a Swarm\r\n\r\n```typescript\r\nconst swarm = hive.spawnSwarm();\r\n```\r\n\r\n## Using the Swarm\r\n\r\n```typescript\r\nconst result = await swarm.generateText({\r\n  content: 'Can I talk to someone about your B2B SaaS products?'\r\n});\r\n\r\nconsole.log(result.text);\r\nconsole.log(result.activeAgent.name);\r\nconsole.log(result.context);\r\n```\r\n\r\n## Creating a swarm directly\r\n```typescript\r\nconst swarm = new Swarm({\r\n    defaultModel: openai('gpt-4o-mini'),\r\n    name: 'Test Swarm',\r\n    queen: agent,\r\n    initialContext: {}\r\n})\r\n```\r\n\r\n# API Reference\r\n\r\n## Agent\r\n\r\n```typescript\r\nnew Agent<SWARM_CONTEXT>(options: AgentOptions<SWARM_CONTEXT>)\r\n```\r\n> [!IMPORTANT]\r\n> Note that `SWARM_CONTEXT` defaults to `any` if a template value is not provided. Be careful! \r\nContexts should be JSON-serializable.\r\n\r\n### Agent Options `AgentOptions<SWARM_CONTEXT>`\r\n\r\n| Name | Type | Description |\r\n|------|------|-------------|\r\n| `name` | `string` | The agent's name; used in handover |\r\n| `description` | `string` | A description for the agent |\r\n| `instructions` | `string \\| ((context: SWARM_CONTEXT) => string)` | A prompt string, prompt nunjucks template, or prompt builder function. The swarm's context object will be passed in to the template or to the builder function. |\r\n| `tools` | `Record<string, AgentTool<SWARM_CONTEXT>>` | The tools available to the agent. Each key should be the `name` of the tool, and the value is the tool or handover tool. |\r\n| `toolChoice` | `CoreToolChoice<any>` | Force the agent to call one of the provided tools, or to call a specific tool. Useful when you want to force the agent to call a tool and then return handover back to the `queen` / router agent without generating text, since the first text response from the LLM will return the result of the user. |\r\n| `model` | `LanguageModel (optional)` | The LLM to use; defaults to whatever the default LLM is for the swarm that's executing the agent. |\r\n| `maxTurns` | `number (optional)` | Max number of iterative calls of tool calls & tool execution; use it to prevent infinite tool call loops. |\r\n| `temperature` | `number (optional)` | Set the LLM's temperature |\r\n\r\n### Agent tool `AgentTool<SWARM_CONTEXT>`\r\n`AgentTool` is a wrapper on the AI SDK's native `tool`/`CoreTool` types that represents a callable tool that \r\nperforms some execution, that hands off execution to the next agent, that updates the context of the swarm, or some \r\ncombination thereof. \r\n\r\n| Property      | Type                                                                         | description                                                                                                                    |\r\n|---------------|------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|\r\n| `type`        | `'function' \\| 'handover'`                                                   | indicates whether the tool is a normal tool, or should transfer execution to another agent                                     |\r\n| `description` | `string`                                                                     | information about what the tool does and when it should be called                                                              |\r\n| `parameters`  | `z.AnyZodObject`                                                             | a zod schema describing the shape of the parameters; use the magic `swarmContext` key to request access to the swarm's context |\r\n| `execute`     | `(parameters, options) => Promise<({result: string} \\| {agent: Agent}) & {context?: Partial<SWARM_CONTEXT>}>` | an async executor for the tool. The shape of `parameters` is inferred from the zod schema.|\r\n\r\nThe wrapping of the AI SDK's native `tool` with `AgentTool` allows us to achieve a couple of things:\r\n- distinguish between function tools and handover tools; and properly execute handovers on the client side\r\n- allow tools to request access to the swarm's context at execution-time through the `parameters` object \r\nin a type-safe way, _without_ passing the swarm context parameter key to the LLM, since we don't want the LLM to \r\ntry to generate (hallucinate) the context. The `swarmContext` magic parameter is stripped before the tool is passed to the\r\nLLM\r\n- allow tools to update the swarm's context after execution using the optional `context?: Partial<SWARM_CONTEXT>` key \r\nin the tool executor's return value\r\n\r\nThe simplest implementation of a tool specifies `type: 'tool'` and returns a tool result in the executor. This will \r\nbehave like a normal tool\r\n```typescript\r\nnew Agent({\r\n    name: 'Weather agent',\r\n    description: 'Gets the weather',\r\n    tools: {\r\n        get_current_weather: {\r\n            type: 'function',\r\n            description: 'Get the weather in a given city',\r\n            parameters: z.object({\r\n                city: z.string().describe('The city to get the weather for.'),\r\n            }),\r\n            execute: async ({city}, options) => {\r\n                console.log(`Executing weather tool.`)\r\n                return {\r\n                    result: \"70 degrees fahrenheit and sunny\",\r\n                }\r\n            }\r\n        },\r\n    }\r\n})\r\n```\r\n\r\nA handover tool specifies `type: 'handover'`, and will result in the active agent being transferred to the specified agent before \r\nswarm execution continues. Make sure to return an agent!\r\n```typescript\r\nnew Agent({\r\n    name: 'receptionist',\r\n    description: 'a receptionist that handles routing conversations and calls',\r\n    tools: {\r\n        transfer_to_weatherman: {\r\n            type: 'handover', // type: 'handover' is a framework level abstraction and will be converted under the hood\r\n            description: 'Transfer the conversation to weatherman',\r\n            parameters: z.object({}),\r\n            execute: async () => {\r\n                return {\r\n                    agent: salesAgent, // return an `agent` rather than a `result`\r\n                }\r\n            }\r\n        }\r\n    }\r\n})\r\n```\r\n\r\n> [!TIP]\r\n> The swarm's context isn't just for system prompts! Tools can request access \r\n> to the swarm's context, and both regular and handover tools can update it.\r\n\r\nTools can access the swarm's context using the magic `swarmContext` key in the `parameters` object. If this key is \r\nspecified, the tool's `execute` method will receive the current value of the swarm's context. \r\n\r\nSimilarly, a tool can update the swarm context by returning a `context` update in the object returned by `execute` - \r\nthe context object should be a `Partial<SWARM_CONTEXT>` and will be merged into the swarm context after the tool's \r\nexecution. It can be used to set (and to unset!) keys on the context.\r\n\r\nThis can be a useful way to allow agents to pass messages, values, or even instructions to each other!\r\n\r\n```typescript\r\ninterface SalesContext {\r\n    topic: string | null\r\n    weather: string | null\r\n}\r\n// Answers questions in text - as soon as text is generated it will be returned to the user!\r\nconst salesAgent: Agent<SalesContext> = new Agent<SalesContext>({\r\n    name: 'Kyle the salesman',\r\n    description: 'Agent to answer sales queries',\r\n    // `topic` in the template will be filled in from the context\r\n    instructions: 'You are a salesman for Salesforce. ' +\r\n        'You answer all sales questions about salesforce to the best of your ability.' +\r\n        'You are talking to a customer about {{topic}}, a salesforce product'\r\n    \r\n})\r\n\r\nconst receptionistAgent: Agent<SalesContext> = new Agent<SalesContext>({\r\n    name: 'Receptionist',\r\n    description: 'A simple agent that answers user queries',\r\n    instructions: 'You help users talk to the person that they want to talk to by routing them appropriately.',\r\n    tools: {\r\n        get_current_weather: {\r\n            type: 'function',\r\n            description: 'Get the weather in a given city',\r\n            parameters: z.object({\r\n                city: z.string().describe('The city to get the weather for.'),\r\n                // magic parameter to request access to swarm context\r\n                swarmContext: z.custom<SalesContext>()\r\n            }),\r\n            // when swarm context is requested in the parameters, it can be accessed here!\r\n            execute: async ({city, swarmContext}, options) => {\r\n                console.log(`Swarm context:`, swarmContext)\r\n                // Return an object that includes a result for the tool call, and a context update.\r\n                return {\r\n                    result: \"70 degrees fahrenheit and sunny\",\r\n                    context: {\r\n                        weather: '70 degrees and sunny'\r\n                    }\r\n                }\r\n            }\r\n        },\r\n        transfer_to_sales: {\r\n            type: 'handover',\r\n            description: 'Transfer the conversation to a sales agent who can answer questions about sales',\r\n            parameters: z.object({\r\n                topic: z.string().describe('The topic of the sales conversation')\r\n            }),\r\n            execute: async ({topic}) => {\r\n                return {\r\n                    agent: salesAgent,\r\n                    // update the context with the information that the sales agent will need in its' instructions.\r\n                    context: {topic}\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n})\r\n```\r\n\r\n## Hive\r\n\r\n```typescript\r\nnew Hive<HIVE_CONTEXT>(options: HiveOptions<HIVE_CONTEXT>)\r\n```\r\n\r\n### Hive Options `HiveOptions<HIVE_CONTEXT>`\r\n\r\n| Name | Type | Description |\r\n|------|------|-------------|\r\n| `defaultModel` | `LanguageModel (optional)` | The default language model to be used by agents in the swarm if not specified individually |\r\n| `queen` | `Agent<HIVE_CONTEXT>` | The initial agent (often an orchestrator) that serves as the entry point for the swarm |\r\n| `defaultContext` | `HIVE_CONTEXT (optional)` | The default context object to be used when spawning new swarms |\r\n\r\n### Methods\r\n#### `spawnSwarm`\r\n- `spawnSwarm(options?: HiveCreateSwarmOptions<HIVE_CONTEXT>): Swarm<HIVE_CONTEXT>` - creates a swarm based off the hive, \r\nwith the ability to override certain values if desired\r\n\r\n## Swarm\r\n\r\n```typescript\r\nnew Swarm<SWARM_CONTEXT>(options: SwarmOptions<SWARM_CONTEXT>)\r\n```\r\n\r\n### Swarm Options `SwarmOptions<SWARM_CONTEXT>`\r\n\r\n| Name | Type | Description                                                                                                                 |\r\n|------|------|-----------------------------------------------------------------------------------------------------------------------------|\r\n| `defaultModel` | `LanguageModel (optional)` | The default language model to be used by agents in the swarm if not specified individually                                  |\r\n| `queen` | `Agent<SWARM_CONTEXT>` | The initial agent (often an orchestrator) that serves as the entry point for the swarm                                      |\r\n| `initialContext` | `SWARM_CONTEXT` | The initial context object for the swarm                                                                                    |\r\n| `messages` | `Array<SwarmMessage> (optional)` | Initial messages for the swarm, if any                                                                                      |\r\n| `name` | `string (optional)` | A name for the swarm instance                                                                                               |\r\n| `maxTurns` | `number (optional)` | Maximum number of turns (tool call & execution iterations) allowed in a single invocation; use to prevent infinite loops    |\r\n| `returnToQueen` | `boolean (optional)` | Whether to return control to the queen agent after each interaction, or if the currently-active agent should remain active. |\r\n\r\n> [!NOTE]\r\n> A `SwarmMessage` is extended from `CoreMessage` in the AI SDK, with the exception that each `CoreAssistantMessage` has \r\n> a `sender` property set to the `name` of the `agent` in the swarm that generated it.\r\n\r\n### Methods\r\n\r\n#### `generateText`\r\n```typescript\r\ngenerateText(options: SwarmInvocationOptions<SWARM_CONTEXT>): Promise<GenerateTextResult>\r\n```\r\nGenerate text with the swarm. Options:\r\n\r\n| Property | Type | Description                                                                                                                                         |\r\n|----------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------|\r\n| `contextUpdate` | `Partial<SWARM_CONTEXT>` | Optional. Partial update to the swarm context.                                                                                                      |\r\n| `setAgent` | `Agent<SWARM_CONTEXT>` | Optional. Sets a specific agent for the swarm invocation, overriding the currently active agent                                                     |\r\n| `maxTurns` | `number` | Optional. Maximum number of turns allowed for the swarm invocation.                                                                                 |\r\n| `returnToQueen` | `boolean` | Optional. Determines if control of the swarm should be returned to the queen after completion; overrides the property of the same name on the swarm |\r\n| `onStepFinish` | `(event: StepResult<any>, context: SWARM_CONTEXT) => Promise<void> \\| void` | Optional. Callback function executed after each step finishes.                                                                                      |\r\n| `content` | `UserContent` | Required if `messages` is not provided. The content for the swarm invocation.                                                                       |\r\n| `messages` | `Array<SwarmMessage>` | Required if `content` is not provided. An array of swarm messages for the invocation.                                                               |\r\n\r\nReturns: `GenerateTextResult` (type from the [AI SDK](https://sdk.vercel.ai/docs/reference/ai-sdk-core/generate-text))\r\n\r\nNotes: \r\n- The `content` and `messages` properties are mutually exclusive. You must provide either `content` or `messages`, but not both.\r\nBy default, you should probably only need to set one of these.\r\n- Swarms can be used in a stateless manner by always setting the `messages` array rather than `content`, and by always setting `returnToQueen` or using `setAgent`\r\n\r\n#### `streamText`\r\n```typescript \r\nstreamText(options: SwarmInvocationOptions<SWARM_CONTEXT> & SwarmStreamingOptions): {\r\n    finishReason:  Promise<LanguageModelV1FinishReason>,\r\n    activeAgent: Promise<Agent>,\r\n    text: Promise<string>,\r\n    messages: Promise<Array<SwarmMessage>>,\r\n    context: Promise<SWARM_CONTEXT>,\r\n    textStream: AsyncIterableStream<string>,\r\n    fullStream:  AsyncIterableStream<ExtendedTextStreamPart<any>>\r\n}\r\n```\r\n\r\nStream text and tool calls from the stream. \r\n`SwarmInvocationOptions & SwarmStreamingOptions`:\r\n\r\n| Property | Type | Description                                                                                                                                         |\r\n|----------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------|\r\n| `contextUpdate` | `Partial<SWARM_CONTEXT>` | Optional. Partial update to the swarm context.                                                                                                      |\r\n| `setAgent` | `Agent<SWARM_CONTEXT>` | Optional. Sets a specific agent for the swarm invocation, overriding the currently active agent                                                     |\r\n| `maxTurns` | `number` | Optional. Maximum number of turns allowed for the swarm invocation.                                                                                 |\r\n| `returnToQueen` | `boolean` | Optional. Determines if control of the swarm should be returned to the queen after completion; overrides the property of the same name on the swarm |\r\n| `onStepFinish` | `(event: StepResult<any>, context: SWARM_CONTEXT) => Promise<void> \\| void` | Optional. Callback function executed after each step finishes.                                                                                      |\r\n| `content` | `UserContent` | Required if `messages` is not provided. The content for the swarm invocation.                                                                       |\r\n| `messages` | `Array<SwarmMessage>` | Required if `content` is not provided. An array of swarm messages for the invocation.                                                               |\r\n| `experimental_toolCallStreaming` | `boolean (optional)` | Whether to enable experimental tool call streaming. Enabled by default unless explicitly disabled by setting to `false` |\r\n\r\nNotes:\r\n- The `content` and `messages` properties are mutually exclusive. You must provide either `content` or `messages`, but not both.\r\n  By default, you should probably only need to set one of these.\r\n- It is recommended to keep `experimental_toolCallStreaming` enabled; as it will allow you to read the name of the function \r\nthat is being called as soon as the call begins; this can be very useful in realtime or latency-critical applications so\r\nthat you can take actions or provide feedback to the end-user about what the agent(s) are doing.\r\n\r\nReturn value:\r\n> [!IMPORTANT]\r\n> Unlike `Swarm.generateText`, this method returns immediately. Promise values resolve once the swarm has finished\r\n> generating.\r\n\r\n| Property | Type | Description                                                                                                                                                                               |\r\n|----------|------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\r\n| `finishReason` | `Promise<LanguageModelV1FinishReason>` | A promise that resolves to the final finish reason of the final agent that executes. Type is taken from the AI SDK                                                                        |\r\n| `activeAgent` | `Promise<Agent>` | A promise that resolves to the agent that is active after streaming finishes. If `returnToQueen` is set, this will always be the queen. Otherwise, it will be whatever the last agent was |\r\n| `text` | `Promise<string>` | A promise that resolves to the text generated at the end of the swarm's generation. |\r\n| `messages` | `Promise<SwarmMessage>` | A promise that resolves to the messages generated by the swarm duriung streaming | \r\n| `context` | `Promise<SWARM_CONTEXT>` | A promise that resolves to the state of the swarm's context once the swarm has finished streaming |\r\n| `textStream` | `AsyncIterableStream<string>` | Async iterable stream that yields the text chunks generated by the LLM once text (rather than tool calls) is being generated |\r\n| `fullStream`| `AsyncIterableStream<ExtendedTextStreamPart<any>>` | Async iterable stream that contains the individual deltas for streaming, including text deltas, tool deltas, the finished tool call and tool results. See `streamText` in the AI SDK for details; note that `experimental_toolCallStreaming` is enabled by default. |\r\n\r\n`ExtendedTextStreamPart` is etended from the [AI SDK's `TextStreamPart`](https://sdk.vercel.ai/docs/reference/ai-sdk-core/stream-text#full-stream.text-stream-part),\r\nwith several important additions:\r\n1. Each delta has an `agent` key set to an object (`agent: { name: string, id: string }`) containing the `id` (`Agent.uuid`) and `name` (`Agent.name`) of the \r\nagent that generated the delta. This allows you to easily determine which agent is calling tools or generating text \r\nduring stream processing; and can be very useful in real-time applications. \r\n2. A `TextStreamPart` with `{type: 'tool-result'}` will be included in streams for handovers, and in addition to the \r\n`agent` key described above which describes which agent was responsible for the delta, has a `handedOverTo` property \r\nindicating which agent the handover tool is transferring control to. The structure (`handedOverTo?: { name: string, id: string }`) \r\nis the same as for `agent`.\r\n\r\nIn both cases, the `Agent`'s `name` and `id` are used rathern than the `Agent` itself to preserve JSON-serializability.\r\n\r\n\r\n#### `getContext`\r\n```typescript \r\ngetContext(): Readonly<SWARM_CONTEXT>\r\n```\r\nRetrieve the Swarm's context\r\n\r\n#### `updateContext`\r\n```typescript \r\nupdateContext(update: Partial<SWARM_CONTEXT>): Readonly<SWARM_CONTEXT>\r\n```\r\nForce-update the swarm's context external to any agent interactions. \r\n\r\n# Examples\r\n\r\n## Creating a Simple Sales Swarm\r\n\r\n```typescript\r\nimport { Agent, Hive, Swarm } from 'agentswarm';\r\nimport { openai } from '@ai-sdk/openai';\r\nimport z from 'zod';\r\n\r\ninterface SalesContext {\r\n  topic: string | null;\r\n  weather: string | null;\r\n}\r\n\r\nconst salesAgent = new Agent<SalesContext>({\r\n  name: 'Sales Agent',\r\n  description: 'Handles sales-related queries',\r\n  instructions: 'You are a sales representative for our company trying to sell {{topic}}',\r\n});\r\n\r\nconst receptionistAgent = new Agent<SalesContext>({\r\n  name: 'Receptionist',\r\n  description: 'Routes user queries to appropriate agents',\r\n  instructions: 'You help users by routing them to the appropriate agent...',\r\n  tools: {\r\n    transfer_to_sales: {\r\n      type: 'handover',\r\n      description: 'Transfer to sales agent',\r\n      parameters: z.object({\r\n        topic: z.string().describe('Sales topic'),\r\n      }),\r\n      execute: async ({ topic }) => ({\r\n        agent: salesAgent,\r\n        context: { topic },\r\n      }),\r\n    },\r\n  },\r\n});\r\n\r\nconst hive = new Hive<SalesContext>({\r\n  queen: receptionistAgent,\r\n  defaultModel: openai('gpt-4o-mini'),\r\n  defaultContext: { topic: null, weather: null },\r\n});\r\n\r\nconst swarm = hive.spawnSwarm();\r\n\r\nconst result = await swarm.generateText({\r\n  content: 'I want to learn about your product pricing.',\r\n});\r\n\r\nconsole.log(result.text);\r\nconsole.log(result.activeAgent.name);\r\nconsole.log(result.context);\r\n```\r\n\r\n## Using with Next.js and useChat\r\n\r\n### API Route (`app/api/chat/route.ts`)\r\n\r\n```typescript\r\nimport { openai } from '@ai-sdk/openai';\r\nimport { convertToCoreMessages } from 'ai';\r\nimport { Agent, Swarm } from 'agentswarm';\r\nimport z from 'zod';\r\n\r\ninterface ChatContext {\r\n  topic: string | null;\r\n  userInfo: string | null;\r\n}\r\n\r\n// Define your agents\r\nconst supportAgent = new Agent<ChatContext>({\r\n  name: 'Support Agent',\r\n  description: 'Handles customer support queries',\r\n  instructions: 'You are a helpful customer support agent. {{topic ? `You are discussing: ${topic}` : \"\"}}',\r\n});\r\n\r\nconst salesAgent = new Agent<ChatContext>({\r\n  name: 'Sales Agent', \r\n  description: 'Handles sales and product inquiries',\r\n  instructions: 'You are a sales representative. Help customers understand our products and pricing.',\r\n});\r\n\r\nconst routerAgent = new Agent<ChatContext>({\r\n  name: 'Router',\r\n  description: 'Routes conversations to appropriate agents',\r\n  instructions: 'You help route customers to the right department.',\r\n  tools: {\r\n    transfer_to_support: {\r\n      type: 'handover',\r\n      description: 'Transfer to customer support for technical issues',\r\n      parameters: z.object({\r\n        issue: z.string().describe('Description of the support issue'),\r\n      }),\r\n      execute: async ({ issue }) => ({\r\n        agent: supportAgent,\r\n        context: { topic: issue },\r\n      }),\r\n    },\r\n    transfer_to_sales: {\r\n      type: 'handover',\r\n      description: 'Transfer to sales for product and pricing questions',\r\n      parameters: z.object({\r\n        interest: z.string().describe('What the customer is interested in'),\r\n      }),\r\n      execute: async ({ interest }) => ({\r\n        agent: salesAgent,\r\n        context: { topic: interest },\r\n      }),\r\n    },\r\n  },\r\n});\r\n\r\n// Create the swarm\r\nconst swarm = new Swarm<ChatContext>({\r\n  defaultModel: openai('gpt-4o-mini'),\r\n  queen: routerAgent,\r\n  initialContext: { topic: null, userInfo: null },\r\n});\r\n\r\nexport async function POST(req: Request) {\r\n  const { messages } = await req.json();\r\n\r\n  // Convert useChat messages to Core messages\r\n  const coreMessages = convertToCoreMessages(messages);\r\n\r\n  const result = swarm.streamText({\r\n    messages: coreMessages,\r\n  });\r\n\r\n  return result.toDataStreamResponse();\r\n}\r\n```\r\n\r\n### Client Component (`app/page.tsx`)\r\n\r\n```typescript\r\n'use client';\r\n\r\nimport { useChat } from '@ai-sdk/react';\r\n\r\nexport default function Chat() {\r\n  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({\r\n    api: '/api/chat',\r\n  });\r\n\r\n  return (\r\n    <div className=\"flex flex-col w-full max-w-md py-24 mx-auto stretch\">\r\n      {messages.map((message) => (\r\n        <div key={message.id} className=\"whitespace-pre-wrap\">\r\n          <strong>{message.role === 'user' ? 'User: ' : 'AI: '}</strong>\r\n          {message.content}\r\n        </div>\r\n      ))}\r\n\r\n      <form onSubmit={handleSubmit}>\r\n        <input\r\n          className=\"fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl\"\r\n          value={input}\r\n          placeholder=\"Say something...\"\r\n          onChange={handleInputChange}\r\n          disabled={isLoading}\r\n        />\r\n      </form>\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n### Alternative: Using with Custom Data Stream\r\n\r\nIf you need custom data alongside the messages:\r\n\r\n```typescript\r\n// API Route with custom data\r\nexport async function POST(req: Request) {\r\n  const { messages } = await req.json();\r\n\r\n  const result = swarm.streamText({\r\n    messages: convertToCoreMessages(messages),\r\n  });\r\n\r\n  return result.toDataStreamResponse({\r\n    sendUsage: true, // Include token usage\r\n    experimental_sendFinish: true, // Include finish events\r\n  });\r\n}\r\n```\r\n\r\n```typescript\r\n// Client with data access\r\n'use client';\r\n\r\nimport { useChat } from '@ai-sdk/react';\r\n\r\nexport default function ChatWithData() {\r\n  const { messages, input, handleInputChange, handleSubmit, data } = useChat();\r\n\r\n  return (\r\n    <div className=\"flex flex-col w-full max-w-md py-24 mx-auto stretch\">\r\n      {/* Display any custom data */}\r\n      {data && (\r\n        <pre className=\"text-xs bg-gray-100 p-2 rounded\">\r\n          {JSON.stringify(data, null, 2)}\r\n        </pre>\r\n      )}\r\n\r\n      {messages.map((message) => (\r\n        <div key={message.id} className=\"whitespace-pre-wrap\">\r\n          <strong>{message.role === 'user' ? 'User: ' : 'AI: '}</strong>\r\n          {message.content}\r\n        </div>\r\n      ))}\r\n\r\n      <form onSubmit={handleSubmit}>\r\n        <input\r\n          className=\"fixed bottom-0 w-full max-w-md p-2 mb-8 border border-gray-300 rounded shadow-xl\"\r\n          value={input}\r\n          placeholder=\"Say something...\"\r\n          onChange={handleInputChange}\r\n        />\r\n      </form>\r\n    </div>\r\n  );\r\n}\r\n```\r\n\r\n## Streaming\r\n\r\n```typescript\r\nconst result = swarm.streamText({\r\n    content: 'I\\'d like to talk to someone about salesforce AI agents'\r\n})\r\n\r\n\r\nlet handedOver: boolean = false\r\nlet activeAgentName: string = agent.name\r\nfor await (const chunk of result.fullStream) {\r\n    if (chunk.type === 'tool-result' && chunk.handedOverTo) {\r\n        handedOver = true\r\n        console.log(`Handover executed to agent ${chunk.handedOverTo.name}!`)\r\n    }\r\n    if (chunk.type === 'tool-call-streaming-start') {\r\n        console.log(`Agent ${chunk.agent.name} is calling ${chunk.toolName}; arguments are being generated`)\r\n    }\r\n    if (chunk.agent.name !== activeAgentName) {\r\n        console.log(`Active agent changed:`, chunk.agent.name) \r\n        activeAgentName = chunk.agent.name\r\n    }\r\n}\r\n\r\nlet streamedText = ''\r\nfor await (const textChunk of result.textStream) {\r\n    // chunks of `textStream` are just strings :)\r\n    streamedText += textChunk\r\n}\r\nstreamedText === await result.text // true \r\n\r\n```\r\n\r\n# Changelog\r\n\r\n## [0.1.2] - 2024-01-xx\r\n\r\n### Fixed\r\n\r\n- **Data Stream Protocol Compatibility**: Fixed `\"data\" parts expect an array value.` error when using with Vercel AI SDK's `useChat` hook\r\n  - Corrected stream part type codes to match AI SDK v4+ protocol:\r\n    - Tool call streaming start: `12:` → `b:`\r\n    - Tool call delta: `13:` → `c:`\r\n    - Tool result: `11:` → `a:`\r\n    - Error events: `e:` → `3:`\r\n    - Step events: Updated to proper format codes\r\n  - Fixed file/annotation parts to use proper array format: `8:[...]\\n`\r\n  - Enhanced error message escaping for proper JSON string format\r\n  - Updated tests to reflect correct stream protocol format\r\n\r\n### Improved\r\n\r\n- Added comprehensive Next.js examples with `useChat` integration\r\n- Enhanced README with proper installation instructions and compatibility notes\r\n- Added complete API route and client component examples\r\n\r\n## [0.1.1] - 2024-01-xx\r\n\r\n### Initial Release\r\n\r\n- Core swarm functionality with multi-agent orchestration\r\n- Support for agent handovers and context sharing\r\n- Tool calling and execution framework\r\n- Streaming and non-streaming text generation\r\n- TypeScript support with full type safety\r\n","readmeFilename":"README.md"}