Skip to content

Commit 8b4daf4

Browse files
committed
updated
1 parent 9709b44 commit 8b4daf4

File tree

2 files changed

+5
-355
lines changed

2 files changed

+5
-355
lines changed

‎README.md‎

Lines changed: 5 additions & 355 deletions
Original file line numberDiff line numberDiff line change
@@ -1,359 +1,9 @@
11
![Swarm Logo](assets/logo.png)
22

3-
# Swarm (experimental, educational)
3+
# Async Swarm (experimental, educational)
44

5-
An educational framework exploring ergonomic, lightweight multi-agent orchestration.
5+
Here is the original Swarm repo:
6+
https://github.com/openai/swarm
67

7-
> [!WARNING]
8-
> Swarm is currently an experimental sample framework intended to explore ergonomic interfaces for multi-agent systems. It is not intended to be used in production, and therefore has no official support. (This also means we will not be reviewing PRs or issues!)
9-
>
10-
> The primary goal of Swarm is to showcase the handoff & routines patterns explored in the [Orchestrating Agents: Handoffs & Routines](https://cookbook.openai.com/examples/orchestrating_agents) cookbook. It is not meant as a standalone library, and is primarily for educational purposes.
11-
12-
## Install
13-
14-
Requires Python 3.10+
15-
16-
```shell
17-
pip install git+ssh://git@github.com/openai/swarm.git
18-
```
19-
20-
or
21-
22-
```shell
23-
pip install git+https://github.com/openai/swarm.git
24-
```
25-
26-
## Usage
27-
28-
```python
29-
from swarm import Swarm, Agent
30-
31-
client = Swarm()
32-
33-
def transfer_to_agent_b():
34-
return agent_b
35-
36-
37-
agent_a = Agent(
38-
name="Agent A",
39-
instructions="You are a helpful agent.",
40-
functions=[transfer_to_agent_b],
41-
)
42-
43-
agent_b = Agent(
44-
name="Agent B",
45-
instructions="Only speak in Haikus.",
46-
)
47-
48-
response = client.run(
49-
agent=agent_a,
50-
messages=[{"role": "user", "content": "I want to talk to agent B."}],
51-
)
52-
53-
print(response.messages[-1]["content"])
54-
```
55-
56-
```
57-
Hope glimmers brightly,
58-
New paths converge gracefully,
59-
What can I assist?
60-
```
61-
62-
## Table of Contents
63-
64-
- [Overview](#overview)
65-
- [Examples](#examples)
66-
- [Documentation](#documentation)
67-
- [Running Swarm](#running-swarm)
68-
- [Agents](#agents)
69-
- [Functions](#functions)
70-
- [Streaming](#streaming)
71-
- [Evaluations](#evaluations)
72-
- [Utils](#utils)
73-
74-
# Overview
75-
76-
Swarm focuses on making agent **coordination** and **execution** lightweight, highly controllable, and easily testable.
77-
78-
It accomplishes this through two primitive abstractions: `Agent`s and **handoffs**. An `Agent` encompasses `instructions` and `tools`, and can at any point choose to hand off a conversation to another `Agent`.
79-
80-
These primitives are powerful enough to express rich dynamics between tools and networks of agents, allowing you to build scalable, real-world solutions while avoiding a steep learning curve.
81-
82-
> [!NOTE]
83-
> Swarm Agents are not related to Assistants in the Assistants API. They are named similarly for convenience, but are otherwise completely unrelated. Swarm is entirely powered by the Chat Completions API and is hence stateless between calls.
84-
85-
## Why Swarm
86-
87-
Swarm explores patterns that are lightweight, scalable, and highly customizable by design. Approaches similar to Swarm are best suited for situations dealing with a large number of independent capabilities and instructions that are difficult to encode into a single prompt.
88-
89-
The Assistants API is a great option for developers looking for fully-hosted threads and built in memory management and retrieval. However, Swarm is an educational resource for developers curious to learn about multi-agent orchestration. Swarm runs (almost) entirely on the client and, much like the Chat Completions API, does not store state between calls.
90-
91-
# Examples
92-
93-
Check out `/examples` for inspiration! Learn more about each one in its README.
94-
95-
- [`basic`](examples/basic): Simple examples of fundamentals like setup, function calling, handoffs, and context variables
96-
- [`triage_agent`](examples/triage_agent): Simple example of setting up a basic triage step to hand off to the right agent
97-
- [`weather_agent`](examples/weather_agent): Simple example of function calling
98-
- [`airline`](examples/airline): A multi-agent setup for handling different customer service requests in an airline context.
99-
- [`support_bot`](examples/support_bot): A customer service bot which includes a user interface agent and a help center agent with several tools
100-
- [`personal_shopper`](examples/personal_shopper): A personal shopping agent that can help with making sales and refunding orders
101-
102-
# Documentation
103-
104-
![Swarm Diagram](assets/swarm_diagram.png)
105-
106-
## Running Swarm
107-
108-
Start by instantiating a Swarm client (which internally just instantiates an `OpenAI` client).
109-
110-
```python
111-
from swarm import Swarm
112-
113-
client = Swarm()
114-
```
115-
116-
### `client.run()`
117-
118-
Swarm's `run()` function is analogous to the `chat.completions.create()` function in the Chat Completions API – it takes `messages` and returns `messages` and saves no state between calls. Importantly, however, it also handles Agent function execution, hand-offs, context variable references, and can take multiple turns before returning to the user.
119-
120-
At its core, Swarm's `client.run()` implements the following loop:
121-
122-
1. Get a completion from the current Agent
123-
2. Execute tool calls and append results
124-
3. Switch Agent if necessary
125-
4. Update context variables, if necessary
126-
5. If no new function calls, return
127-
128-
#### Arguments
129-
130-
| Argument | Type | Description | Default |
131-
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- |
132-
| **agent** | `Agent` | The (initial) agent to be called. | (required) |
133-
| **messages** | `List` | A list of message objects, identical to [Chat Completions `messages`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages) | (required) |
134-
| **context_variables** | `dict` | A dictionary of additional context variables, available to functions and Agent instructions | `{}` |
135-
| **max_turns** | `int` | The maximum number of conversational turns allowed | `float("inf")` |
136-
| **model_override** | `str` | An optional string to override the model being used by an Agent | `None` |
137-
| **execute_tools** | `bool` | If `False`, interrupt execution and immediately returns `tool_calls` message when an Agent tries to call a function | `True` |
138-
| **stream** | `bool` | If `True`, enables streaming responses | `False` |
139-
| **debug** | `bool` | If `True`, enables debug logging | `False` |
140-
141-
Once `client.run()` is finished (after potentially multiple calls to agents and tools) it will return a `Response` containing all the relevant updated state. Specifically, the new `messages`, the last `Agent` to be called, and the most up-to-date `context_variables`. You can pass these values (plus new user messages) in to your next execution of `client.run()` to continue the interaction where it left off – much like `chat.completions.create()`. (The `run_demo_loop` function implements an example of a full execution loop in `/swarm/repl/repl.py`.)
142-
143-
#### `Response` Fields
144-
145-
| Field | Type | Description |
146-
| --------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
147-
| **messages** | `List` | A list of message objects generated during the conversation. Very similar to [Chat Completions `messages`](https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages), but with a `sender` field indicating which `Agent` the message originated from. |
148-
| **agent** | `Agent` | The last agent to handle a message. |
149-
| **context_variables** | `dict` | The same as the input variables, plus any changes. |
150-
151-
## Agents
152-
153-
An `Agent` simply encapsulates a set of `instructions` with a set of `functions` (plus some additional settings below), and has the capability to hand off execution to another `Agent`.
154-
155-
While it's tempting to personify an `Agent` as "someone who does X", it can also be used to represent a very specific workflow or step defined by a set of `instructions` and `functions` (e.g. a set of steps, a complex retrieval, single step of data transformation, etc). This allows `Agent`s to be composed into a network of "agents", "workflows", and "tasks", all represented by the same primitive.
156-
157-
## `Agent` Fields
158-
159-
| Field | Type | Description | Default |
160-
| ---------------- | ------------------------ | ----------------------------------------------------------------------------- | ---------------------------- |
161-
| **name** | `str` | The name of the agent. | `"Agent"` |
162-
| **model** | `str` | The model to be used by the agent. | `"gpt-4o"` |
163-
| **instructions** | `str` or `func() -> str` | Instructions for the agent, can be a string or a callable returning a string. | `"You are a helpful agent."` |
164-
| **functions** | `List` | A list of functions that the agent can call. | `[]` |
165-
| **tool_choice** | `str` | The tool choice for the agent, if any. | `None` |
166-
167-
### Instructions
168-
169-
`Agent` `instructions` are directly converted into the `system` prompt of a conversation (as the first message). Only the `instructions` of the active `Agent` will be present at any given time (e.g. if there is an `Agent` handoff, the `system` prompt will change, but the chat history will not.)
170-
171-
```python
172-
agent = Agent(
173-
instructions="You are a helpful agent."
174-
)
175-
```
176-
177-
The `instructions` can either be a regular `str`, or a function that returns a `str`. The function can optionally receive a `context_variables` parameter, which will be populated by the `context_variables` passed into `client.run()`.
178-
179-
```python
180-
def instructions(context_variables):
181-
user_name = context_variables["user_name"]
182-
return f"Help the user, {user_name}, do whatever they want."
183-
184-
agent = Agent(
185-
instructions=instructions
186-
)
187-
response = client.run(
188-
agent=agent,
189-
messages=[{"role":"user", "content": "Hi!"}],
190-
context_variables={"user_name":"John"}
191-
)
192-
print(response.messages[-1]["content"])
193-
```
194-
195-
```
196-
Hi John, how can I assist you today?
197-
```
198-
199-
## Functions
200-
201-
- Swarm `Agent`s can call python functions directly.
202-
- Function should usually return a `str` (values will be attempted to be cast as a `str`).
203-
- If a function returns an `Agent`, execution will be transferred to that `Agent`.
204-
- If a function defines a `context_variables` parameter, it will be populated by the `context_variables` passed into `client.run()`.
205-
206-
```python
207-
def greet(context_variables, language):
208-
user_name = context_variables["user_name"]
209-
greeting = "Hola" if language.lower() == "spanish" else "Hello"
210-
print(f"{greeting}, {user_name}!")
211-
return "Done"
212-
213-
agent = Agent(
214-
functions=[greet]
215-
)
216-
217-
client.run(
218-
agent=agent,
219-
messages=[{"role": "user", "content": "Usa greet() por favor."}],
220-
context_variables={"user_name": "John"}
221-
)
222-
```
223-
224-
```
225-
Hola, John!
226-
```
227-
228-
- If an `Agent` function call has an error (missing function, wrong argument, error) an error response will be appended to the chat so the `Agent` can recover gracefully.
229-
- If multiple functions are called by the `Agent`, they will be executed in that order.
230-
231-
### Handoffs and Updating Context Variables
232-
233-
An `Agent` can hand off to another `Agent` by returning it in a `function`.
234-
235-
```python
236-
sales_agent = Agent(name="Sales Agent")
237-
238-
def transfer_to_sales():
239-
return sales_agent
240-
241-
agent = Agent(functions=[transfer_to_sales])
242-
243-
response = client.run(agent, [{"role":"user", "content":"Transfer me to sales."}])
244-
print(response.agent.name)
245-
```
246-
247-
```
248-
Sales Agent
249-
```
250-
251-
It can also update the `context_variables` by returning a more complete `Result` object. This can also contain a `value` and an `agent`, in case you want a single function to return a value, update the agent, and update the context variables (or any subset of the three).
252-
253-
```python
254-
sales_agent = Agent(name="Sales Agent")
255-
256-
def talk_to_sales():
257-
print("Hello, World!")
258-
return Result(
259-
value="Done",
260-
agent=sales_agent,
261-
context_variables={"department": "sales"}
262-
)
263-
264-
agent = Agent(functions=[talk_to_sales])
265-
266-
response = client.run(
267-
agent=agent,
268-
messages=[{"role": "user", "content": "Transfer me to sales"}],
269-
context_variables={"user_name": "John"}
270-
)
271-
print(response.agent.name)
272-
print(response.context_variables)
273-
```
274-
275-
```
276-
Sales Agent
277-
{'department': 'sales', 'user_name': 'John'}
278-
```
279-
280-
> [!NOTE]
281-
> If an `Agent` calls multiple functions to hand-off to an `Agent`, only the last handoff function will be used.
282-
283-
### Function Schemas
284-
285-
Swarm automatically converts functions into a JSON Schema that is passed into Chat Completions `tools`.
286-
287-
- Docstrings are turned into the function `description`.
288-
- Parameters without default values are set to `required`.
289-
- Type hints are mapped to the parameter's `type` (and default to `string`).
290-
- Per-parameter descriptions are not explicitly supported, but should work similarly if just added in the docstring. (In the future docstring argument parsing may be added.)
291-
292-
```python
293-
def greet(name, age: int, location: str = "New York"):
294-
"""Greets the user. Make sure to get their name and age before calling.
295-
296-
Args:
297-
name: Name of the user.
298-
age: Age of the user.
299-
location: Best place on earth.
300-
"""
301-
print(f"Hello {name}, glad you are {age} in {location}!")
302-
```
303-
304-
```javascript
305-
{
306-
"type": "function",
307-
"function": {
308-
"name": "greet",
309-
"description": "Greets the user. Make sure to get their name and age before calling.\n\nArgs:\n name: Name of the user.\n age: Age of the user.\n location: Best place on earth.",
310-
"parameters": {
311-
"type": "object",
312-
"properties": {
313-
"name": {"type": "string"},
314-
"age": {"type": "integer"},
315-
"location": {"type": "string"}
316-
},
317-
"required": ["name", "age"]
318-
}
319-
}
320-
}
321-
```
322-
323-
## Streaming
324-
325-
```python
326-
stream = client.run(agent, messages, stream=True)
327-
for chunk in stream:
328-
print(chunk)
329-
```
330-
331-
Uses the same events as [Chat Completions API streaming](https://platform.openai.com/docs/api-reference/streaming). See `process_and_print_streaming_response` in `/swarm/repl/repl.py` as an example.
332-
333-
Two new event types have been added:
334-
335-
- `{"delim":"start"}` and `{"delim":"end"}`, to signal each time an `Agent` handles a single message (response or function call). This helps identify switches between `Agent`s.
336-
- `{"response": Response}` will return a `Response` object at the end of a stream with the aggregated (complete) response, for convenience.
337-
338-
# Evaluations
339-
340-
Evaluations are crucial to any project, and we encourage developers to bring their own eval suites to test the performance of their swarms. For reference, we have some examples for how to eval swarm in the `airline`, `weather_agent` and `triage_agent` quickstart examples. See the READMEs for more details.
341-
342-
# Utils
343-
344-
Use the `run_demo_loop` to test out your swarm! This will run a REPL on your command line. Supports streaming.
345-
346-
```python
347-
from swarm.repl import run_demo_loop
348-
...
349-
run_demo_loop(agent, stream=True)
350-
```
351-
352-
# Core Contributors
353-
354-
- Ilan Bigio - [ibigio](https://github.com/ibigio)
355-
- James Hills - [jhills20](https://github.com/jhills20)
356-
- Shyamal Anadkat - [shyamal-anadkat](https://github.com/shyamal-anadkat)
357-
- Charu Jaiswal - [charuj](https://github.com/charuj)
358-
- Colin Jarvis - [colin-openai](https://github.com/colin-openai)
359-
- Katia Gil Guzman - [katia-openai](https://github.com/katia-openai)
8+
This repo is a fork of the original Swarm repo with the addition of async functionality used in the YouTube video below:
9+
[![Solana Swarm](assets/solana-swarm.png)](https://youtu.be/cfYrbsBzpFU)

‎assets/solana-swarm.png‎

380 KB
Loading

0 commit comments

Comments
 (0)