Skip to content

Commit

Permalink
Merge pull request #27 from jlowin/docs
Browse files Browse the repository at this point in the history
Add docs
  • Loading branch information
jlowin authored May 13, 2024
2 parents 75afc34 + e9f45e4 commit 87a594c
Show file tree
Hide file tree
Showing 15 changed files with 897 additions and 56 deletions.
Empty file added docs/api/index.md
Empty file.
84 changes: 84 additions & 0 deletions docs/concepts/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Agents

In the ControlFlow framework, an `Agent` represents an AI entity capable of performing tasks and interacting with other agents to achieve desired outcomes. Agents are powered by specialized AI models that excel at specific tasks, such as text generation, decision-making based on unstructured data, or engaging in interactive conversations.

## The Role of Agents in ControlFlow

Agents play a crucial role in the execution of tasks within the ControlFlow framework. When a task is defined and added to a workflow, it is assigned to one or more agents responsible for completing the task based on the provided objectives, instructions, and context.

ControlFlow treats agents as autonomous entities with their own knowledge, capabilities, and tools. By assigning tasks to agents and allowing them to collaborate and communicate with each other, ControlFlow enables the creation of complex AI-powered workflows that can adapt to different scenarios and requirements.

## Defining Agents

To create an agent in ControlFlow, you can use the `Agent` class, which provides a flexible way to define an agent's properties and capabilities.

```python
from controlflow import Agent

writer_agent = Agent(
name="WriterAgent",
description="An AI agent specializing in creative writing tasks.",
tools=[generate_text, summarize_text],
user_access=False
)
```

In this example, we define an agent named "WriterAgent" with a description of its specialization. We also specify the tools available to the agent, which are functions or callable objects that the agent can use to perform specific actions or computations. The `user_access` parameter indicates whether the agent is allowed to interact directly with human users.

## Agent Properties

Agents have several key properties that define their characteristics and capabilities:

- `name` (str): The name of the agent, used for identification and communication purposes.
- `description` (str, optional): A brief description of the agent's specialization or role.
- `tools` (list[AssistantTool | Callable], optional): A list of tools or functions available to the agent for performing tasks.
- `user_access` (bool, optional): Indicates whether the agent is allowed to interact directly with human users.

## Assigning Tasks to Agents

When defining a task using the `Task` class or the `@ai_task` decorator, you can specify the agents responsible for completing the task by setting the `agents` parameter.

```python
from controlflow import Task

write_story_task = Task(
objective="Write a short story about a mysterious artifact.",
result_type=str,
agents=[writer_agent, editor_agent]
)
```

In this example, we assign the "write_story_task" to two agents: "writer_agent" and "editor_agent". These agents will collaborate to complete the task based on their individual capabilities and tools.

## Agent Execution and Communication

During the execution of a workflow, agents assigned to tasks take turns performing actions and communicating with each other to progress towards completing the tasks. The `run()` method of a task automatically handles the selection and iteration of agents until the task is complete.

Agents can communicate with each other by posting messages within the context of a task. These messages are visible to all agents involved in the task and can be used to share information, provide updates, or request assistance.

```python
from controlflow import Flow

with Flow():
story_task = Task(
objective="Write a short story and provide feedback.",
result_type=str,
agents=[writer_agent, editor_agent]
)
result = story_task.run()
```

In this example, the "writer_agent" and "editor_agent" will take turns working on the "story_task". They can communicate with each other by posting messages within the task's context, allowing them to collaborate and provide feedback until the task is complete.

## Agent Tools and User Access

Agents can be equipped with tools, which are functions or callable objects that provide additional capabilities or actions that the agent can perform. These tools can be used by the agent during task execution to perform specific computations, access external resources, or interact with other systems.

The `user_access` property of an agent determines whether the agent is allowed to interact directly with human users. If `user_access` is set to `True`, the agent can use special tools, such as `talk_to_human()`, to send messages to and receive input from human users. This feature is useful for tasks that require human feedback or intervention.


## Conclusion

Agents are a fundamental concept in the ControlFlow framework, representing the AI entities responsible for executing tasks and collaborating to achieve desired outcomes. By defining agents with specific capabilities, tools, and user access permissions, and assigning them to tasks within a workflow, you can create powerful and adaptable AI-powered applications.

ControlFlow provides a flexible and intuitive way to orchestrate the interaction between agents and tasks, enabling developers to focus on defining the objectives and dependencies of their workflows while the framework handles the complexities of agent coordination and communication.
70 changes: 70 additions & 0 deletions docs/concepts/flows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Flows

In the ControlFlow framework, a `Flow` represents a container for an AI-enhanced workflow. It serves as the top-level object that encapsulates tasks, agents, tools, and context, providing a structured environment for AI-powered applications.

## The Role of Flows

Flows play a crucial role in organizing and managing the execution of AI-powered workflows. They provide a high-level abstraction for defining the overall structure and dependencies of tasks, agents, and tools, allowing developers to focus on the desired outcomes rather than the low-level details of agent coordination and communication.

Key aspects of flows include:

- **Task Management**: Flows contain a collection of tasks that define the discrete objectives and goals of the workflow. Tasks can be added to a flow explicitly or implicitly through the use of the `@ai_task` decorator or the `Task` class.

- **Agent Coordination**: Flows manage the assignment and orchestration of agents to tasks. By default, flows are initialized with a default agent, but custom agents can be specified to handle specific tasks or parts of the workflow.

- **Tool Management**: Flows provide a centralized place to define and manage tools that are available to agents throughout the workflow. Tools can be functions or callable objects that agents can use to perform specific actions or computations.

- **Context Sharing**: Flows maintain a consistent context across tasks and agents, allowing for seamless sharing of information and state throughout the workflow. The flow's context can be accessed and modified by tasks and agents, enabling dynamic and adaptive behavior.

## Creating a Flow

To create a flow, you can use the `@flow` decorator on a Python function. The decorated function becomes the entry point for the AI-powered workflow.

```python
from controlflow import flow

@flow
def my_flow():
# Define tasks, agents, and tools here
...
```

Alternatively, you can create a flow object directly using the `Flow` class:

```python
from controlflow import Flow

flow = Flow()
```

## Flow Properties

Flows have several key properties that define their behavior and capabilities:

- `thread` (Thread): The thread associated with the flow, which stores the conversation history and context.
- `tools` (list[AssistantTool | Callable]): A list of tools that are available to all agents in the flow.
- `agents` (list[Agent]): The default agents for the flow, which are used for tasks that do not specify agents explicitly.
- `context` (dict): Additional context or information that is shared across tasks and agents in the flow.

## Running a Flow

To run a flow, you can simply call the decorated function:

```python
@flow
def my_flow():
# Define tasks, agents, and tools here
...

my_flow()
```

When a flow is run, it executes the defined tasks, assigning agents and tools as needed. The flow manages the context across agents.



## Conclusion

Flows are a fundamental concept in the ControlFlow framework, providing a structured and flexible way to define, organize, and execute AI-powered workflows. By encapsulating tasks, agents, tools, and context within a flow, developers can create complex and dynamic applications that leverage the power of AI while maintaining a clear and maintainable structure.

Flows abstract away the low-level details of agent coordination and communication, allowing developers to focus on defining the desired outcomes and objectives of their workflows. With the `@flow` decorator and the `Flow` class, creating and running AI-powered workflows becomes a straightforward and intuitive process.
85 changes: 85 additions & 0 deletions docs/concepts/iteration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Iterative Control

Iterative control lies at the core of agentic workflows, enabling the creation of dynamic and adaptive AI-powered applications. In traditional approaches, the iterative logic is often deeply nested within monolithic AI models, making it challenging to understand, customize, and maintain. ControlFlow takes a different approach by elevating iterative control to a first-class citizen in its API, empowering developers to harness the power of iteration with ease and flexibility.

## The Importance of Iteration in Agentic Workflows

Agentic workflows are characterized by their ability to make decisions, take actions, and adapt based on feedback and changing conditions. This inherent adaptability is achieved through iteration - the process of repeatedly executing a series of steps until a desired outcome is reached.

Consider a simple example of an AI-powered task management system. The system needs to continuously monitor incoming tasks, prioritize them based on predefined criteria, assign them to appropriate agents, and track their progress until completion. This workflow requires iterative control to handle the dynamic nature of tasks and to ensure that the system remains responsive and efficient.

Without iterative control, the system would be limited to handling a fixed set of tasks in a predefined order, lacking the flexibility to adapt to real-world scenarios. Iterative control allows the system to continuously loop through the task management process, making decisions and taking actions based on the current state of tasks and agents.

## ControlFlow: Making Iterative Control Accessible

ControlFlow recognizes the critical role of iterative control in agentic workflows and provides a high-level API that makes it accessible and intuitive for developers. By bringing the concept of iteration to the forefront, ControlFlow enables developers to focus on defining the logic and behavior of their workflows, without getting bogged down in low-level implementation details.

At the heart of ControlFlow's iterative control mechanism lies the `Task` class. A task represents a unit of work that needs to be accomplished by one or more agents. It encapsulates the necessary information, such as the objective, dependencies, and agents responsible for its execution.

To iterate over tasks, ControlFlow provides the `run()` method. This method abstracts away the underlying while loop, allowing developers to express their workflow logic in a concise and readable manner. Under the hood, `run()` intelligently selects agents, manages dependencies, and orchestrates the execution of tasks until the desired outcome is achieved.

Here's an example of how iterative control can be achieved using `run()`:

```python
task = Task(objective="Analyze sales data")
task.run()
```

In this example, the `run()` method takes care of the iterative control flow, repeatedly executing the necessary steps until the task is marked as complete. It handles agent selection, dependency resolution, and progress tracking, freeing developers from the complexities of manual iteration.

## Granular Control with `run_once()` and `agent.run()`

While `run()` provides a high-level abstraction for iterative control, ControlFlow also offers more granular control options through the `run_once()` method and the `agent.run()` function.

The `run_once()` method allows developers to take control of the iteration process by executing a single step at a time. It provides the flexibility to inject custom logic, perform additional checks, or handle specific edge cases within each iteration. By combining `while task.is_incomplete()` with `run_once()`, developers can create custom iteration patterns tailored to their specific requirements.

Here's an example showcasing the usage of `run_once()`:

```python
while task.is_incomplete():
task.run_once()
# Perform additional checks or custom logic
if some_condition:
break
```

In this example, the `run_once()` method is called repeatedly within a while loop until the task is marked as complete. This granular control enables developers to incorporate custom logic, such as breaking out of the loop based on certain conditions or performing additional actions between iterations.

For even more fine-grained control, ControlFlow provides the `agent.run()` function. This function allows developers to explicitly invoke a specific agent to execute a task, bypassing the automated agent selection process. It gives developers complete control over which agent handles a particular task and enables them to create custom agent orchestration patterns.

Here's an example demonstrating the usage of `agent.run()`:

```python
agent1 = Agent(name="DataAnalyst")
agent2 = Agent(name="ReportGenerator")

task1 = Task(objective="Analyze sales data")
task2 = Task(objective="Generate sales report")

agent1.run(task1)
agent2.run(task2)
```

In this example, `agent1` is explicitly assigned to execute `task1`, while `agent2` is assigned to execute `task2`. This level of control is particularly useful when dealing with specialized agents or when implementing complex workflows that require precise agent assignment.

## Balancing Simplicity and Control

One of the key strengths of ControlFlow is its ability to provide a high-level API for iterative control without sacrificing the ability to dive into lower-level details when needed. The framework strikes a balance between simplicity and control, catering to the needs of both rapid development and fine-grained customization.

Developers can start by using the high-level `run()` method to quickly prototype and iterate on their workflows. As their requirements grow more complex, they can gradually transition to using `run_once()` and `agent.run()` to incorporate custom logic and take control of the iteration process.

This gradual descent into lower-level control is made possible by ControlFlow's thoughtful API design. The lower-level methods, such as `run_once()` and `agent.run()`, are not buried deep within the framework but are readily accessible as part of the public API. This accessibility ensures that developers can seamlessly transition between different levels of control without having to navigate through complex abstractions or modify the underlying framework.

Moreover, even at the lowest level of control, ControlFlow maintains a relatively high level of abstraction compared to traditional approaches. Developers can focus on expressing their workflow logic using intuitive concepts like tasks, agents, and dependencies, rather than dealing with raw loops, conditionals, and state management.

This balance between simplicity and control empowers developers to build sophisticated agentic workflows without getting overwhelmed by complexity. It enables them to start simple, iterate quickly, and gradually introduce more advanced control mechanisms as their understanding of the problem domain grows.

## Conclusion

Iterative control is the driving force behind agentic workflows, enabling the creation of dynamic, adaptive, and intelligent AI-powered applications. ControlFlow recognizes the importance of iteration and provides a high-level API that makes it accessible and intuitive for developers.

By offering a spectrum of control options, from the high-level `run()` method to the more granular `run_once()` and `agent.run()` functions, ControlFlow empowers developers to choose the level of control that best suits their needs. Whether they prefer the simplicity of automatic iteration or the precision of manual control, ControlFlow provides a seamless and expressive way to build iterative workflows.

As developers explore the capabilities of ControlFlow, they can leverage the power of iterative control to create sophisticated agentic systems. They can start with the high-level abstractions, gradually diving into lower-level control mechanisms as their requirements evolve. This progressive approach to iterative control enables developers to build robust, adaptive, and maintainable AI-powered workflows.

With ControlFlow, the iterative control flow is no longer an obscure concept hidden within monolithic models but a central and accessible part of the development process. By embracing the power of iteration and leveraging ControlFlow's intuitive API, developers can unlock the full potential of agentic workflows and create intelligent, dynamic, and efficient AI-powered applications.
Loading

0 comments on commit 87a594c

Please sign in to comment.