Skip to content

Commit

Permalink
Update tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
jlowin committed May 13, 2024
1 parent 87a594c commit c1369e5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 23 deletions.
62 changes: 45 additions & 17 deletions docs/concepts/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

In ControlFlow, a `Task` is the fundamental unit of work that represents a specific objective or goal within an AI-powered workflow. Tasks are the primary means of defining and structuring the desired outcomes of an application, acting as a bridge between the AI agents and the application logic.

## The Philosophy of Task-Centric Workflows
## Modeling Application State with Tasks

One of the key roles of tasks in ControlFlow is to model the internal state of an AI-powered application. By defining tasks with clear objectives, dependencies, and result types, developers can create a structured representation of the application's desired outcomes and the steps required to achieve them.

Each task contributes to the overall state of the application, either by producing a specific result or by performing an action that affects the behavior of other tasks or agents. This allows developers to build complex workflows where the results of one task can be used as inputs for subsequent tasks, creating a dynamic and responsive application state.

## The Philosophy of Declarative Task-Based Workflows

ControlFlow takes a unique approach to AI-powered workflows by placing tasks at the center of the design process. Instead of focusing on directly controlling the AI agents' behavior, which can be unpredictable and difficult to manage, ControlFlow encourages developers to define clear, discrete tasks that specify what needs to be accomplished.
ControlFlow embraces a declarative, task-based approach to defining AI workflows. Instead of focusing on directly controlling the AI agents' behavior, which can be unpredictable and difficult to manage, ControlFlow encourages developers to define clear, discrete tasks that specify what needs to be accomplished.

By defining tasks with specific objectives, inputs, outputs, and dependencies, developers can create a structured workflow that guides the AI agents towards the desired outcomes. This task-centric approach allows for more predictable and manageable AI integrations, as the agents are dispatched to complete well-defined tasks rather than being controlled through a complex script that attempts to respond to their stochastic behavior.
By defining tasks with specific objectives, inputs, outputs, and dependencies, developers can create a structured workflow that guides the AI agents towards the desired outcomes. This declarative approach allows for more predictable and manageable AI integrations, as the agents are dispatched to complete well-defined tasks rather than being controlled through complex prompts that attempt to steer their behavior.

The task-based workflow also promotes modularity and reusability. Tasks can be easily composed, reordered, and reused across different workflows, enabling developers to build complex AI applications by combining smaller, self-contained units of work.

## Defining Tasks

In ControlFlow, tasks are typically defined using the `Task` class, which provides a flexible and expressive way to specify task properties and requirements. However, for convenience, ControlFlow also offers the `@ai_task` decorator, which can be used to define tasks using Python functions.
In ControlFlow, tasks can be defined using the `Task` class or the `@task` decorator.

### Using the `Task` Class

The `Task` class is the standard way to define tasks in ControlFlow. It allows you to specify various properties and requirements for a task, such as its objective, instructions, assigned agents, context, dependencies, and more.
The `Task` class provides a flexible way to define tasks by specifying various properties and requirements, such as the objective, instructions, assigned agents, context, dependencies, and more.

```python
from controlflow import Task
Expand All @@ -27,20 +35,20 @@ interests = Task(
)
```

### Using the `@ai_task` Decorator
### Using the `@task` Decorator

The `@ai_task` decorator provides a convenient way to define tasks using Python functions. The decorator accepts many of the same arguments as the `Task` class, and it automatically infers the task's objective, context, and result type from the function definition.
The `@task` decorator offers a convenient way to define and execute tasks using familiar Python functions. The decorator automatically infers the task's objective from the function name, instructions from its docstring, context from the function arguments, and result type from the return annotation. Various additional arguments can be passed to the decorator.

```python
from controlflow import ai_task
from controlflow import task

@ai_task(user_access=True)
@task(user_access=True)
def get_user_name() -> str:
"Politely ask the user for their name."
pass
```

When a decorator-based task is called, it automatically invokes the `run()` method, executing the task and returning its result.
When a decorator-based task is called, it automatically invokes the `run()` method, executing the task and returning its result (or raising an exception if the task fails).

## Task Properties

Expand All @@ -50,8 +58,6 @@ Tasks have several key properties that define their behavior and requirements:
- `instructions` (str, optional): Detailed instructions or guidelines for completing the task.
- `agents` (list[Agent], optional): The AI agents assigned to work on the task.
- `context` (dict, optional): Additional context or information required for the task.
- `subtasks` (list[Task], optional): A list of subtasks that are part of the main task.
- `depends_on` (list[Task], optional): Tasks that must be completed before this task can be executed.
- `result_type` (type, optional): The expected type of the task's result.
- `tools` (list[AssistantTool | Callable], optional): Tools or functions available to the agents for completing the task.
- `user_access` (bool, optional): Indicates whether the task requires human user interaction.
Expand All @@ -62,14 +68,36 @@ Tasks can be executed using the `run()` method, which intelligently selects the

The `result` property of a task holds the outcome or output of the task execution. By specifying a clear `result_type`, developers can ensure that the task's result is structured and can be easily integrated into the application logic. This makes it possible to create complex workflows where the results of one task can be used as inputs for subsequent tasks.

## Task Dependencies and Subtasks
It's important to note that not all tasks require a result. In some cases, a task may be designed to perform an action or produce a side effect without returning a specific value. For example, a task could be used to prompt an agent to say something on the internal thread, which could be useful for later tasks or agents. In such cases, the `result_type` can be set to `None`.

## Task Dependencies and Composition

Tasks can have dependencies on other tasks, which must be completed before the dependent task can be executed. Dependencies can be specified explicitly using the `depends_on` property or implicitly by providing tasks as values in the `context` dictionary.

Subtasks are tasks that are part of a larger, parent task. They can be added to a parent task using the `add_subtask()` method or by creating tasks within a context manager (e.g., `with Task():`). Parent tasks cannot be completed until all their subtasks are finished, although subtasks can be skipped using a special `skip` tool.
Tasks can also be composed hierarchically using subtasks. Subtasks are tasks that are part of a larger, parent task. They can be added to a parent task using the `subtasks` property or by creating tasks within a context manager (e.g., `with Task():`). Parent tasks cannot be completed until all their subtasks are finished, although subtasks can be skipped using a special `skip` tool.

## Modeling Application State with Tasks
## Talking to Humans

ControlFlow provides a built-in mechanism for tasks to interact with human users. By setting the `user_access` property to `True`, a task can indicate that it requires human input or feedback to be completed.

When a task with `user_access=True` is executed, the AI agents assigned to the task will be given access to a special `talk_to_human` tool. This tool allows the agents to send messages to the user and receive their responses, enabling a conversation between the AI and the human.

Here's an example of a task that interacts with a human user:

```python
@task(user_access=True)
def get_user_feedback(product_name: str) -> str:
"""
Ask the user for their feedback on a specific product.
Example conversation:
AI: What do you think about the new iPhone?
Human: I think it's a great phone with impressive features, but it's a bit expensive.
AI: Thank you for your feedback!
"""
pass
```

In ControlFlow, tasks are used to model the internal state of an AI-powered application. By defining tasks with clear objectives, dependencies, and result types, developers can create a structured representation of the application's desired outcomes and the steps required to achieve them.
In this example, the AI agent will use the `talk_to_human` tool to ask the user for their feedback on the specified product. The agent can then process the user's response and store it in the task's `result` property, making it available for use in subsequent tasks or other parts of the application.

This task-centric approach allows for a more modular and manageable integration of AI capabilities into traditional software development workflows. By focusing on defining what needs to be done rather than attempting to control the AI's behavior directly, ControlFlow enables developers to create robust, scalable, and maintainable AI-powered applications.
By leveraging the `user_access` property and the `talk_to_human` tool, developers can create AI-powered workflows that seamlessly integrate human input and feedback, enabling more interactive and user-centric applications.
28 changes: 22 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,28 @@

**ControlFlow is a framework for building agentic LLM workflows.**

ControlFlow provides a structured and intuitive way to create complex AI-powered applications while adhering to traditional software engineering best practices. The resulting workflows are observable, controllable, and easy to trust.
LLMs are powerful AI models that can understand and generate human-like text, enabling them to perform a wide range of tasks. However, building applications with LLMs can be challenging due to their complexity, unpredictability, and potential for hallucinating or generating irrelevant outputs.

ControlFlow provides a structured and intuitive way to create sophisticated agentic workflows while adhereing to traditional software engineering best practices. The resulting applications are observable, controllable, and easy to trust.


!!! question "What's an agentic workflow?"
An agentic workflow treats LLMs as autonomous entities capable of making decisions and performing complex tasks through iterative interactions. At least some of the workflow logic is carried out by the LLMs themselves.


## Design principles
ControlFlow's design is informed by a strong opinon: LLMs are powerful tools, but they are most effective when applied to small, well-defined tasks within a structured workflow.
ControlFlow's design is informed by a strong opinion: LLMs are powerful tools, but they are most effective when applied to small, well-defined tasks within a structured workflow. This approach mitigates many of the challenges associated with LLMs, such as hallucinations, biases, and unpredictable behavior, while also making it easier to debug, monitor, and control the application.

This belief leads to three core design principles that underpin ControlFlow's architecture:

### 🛠️ Specialized over generalized
ControlFlow believes that **single-purpose agents dedicated to a specific tasks** will be more effective than monolithic models that attempt to do everything. By assigning specific tasks to purpose-built models, developers can always ensure that the right tool is used for each job, leading to more efficient, cost-effective, and higher-quality results.
ControlFlow advocates for the use of **specialized, single-purpose LLMs** rather than monolithic models that try to do everything. By assigning specific tasks to purpose-built models, ControlFlow ensures that the right tool is used for each job, leading to more efficient, cost-effective, and higher-quality results.

### 🎯 Outcome over process
ControlFlow defines AI workflows in terms of desired outcomes rather than writing prompts to steer LLM behavior. This **declarative, task-centric approach** lets developers focus on what needs to be done while letting the framework orchestrate agents to achieve those outcomes.
ControlFlow embraces a **declarative approach to defining AI workflows**, allowing developers to focus on the desired outcomes rather than the intricacies of steering LLM behavior. By specifying tasks and their requirements using intuitive constructs, developers can express what needs to be done without worrying about the details of how it will be accomplished.

### 🎛️ Control over autonomy
ControlFlow views agentic workflows as an extension of traditional software development practices. Instead of relying on end-to-end AI systems that make all workflow decisions autonomously, ControlFlow is **explicit by default**, allowing developers to delegate only as much work to AI as they require. This ensures that developers maintain visibility and control over their applications, as well as their preferred methods of testing and debugging.
ControlFlow recognizes the importance of balancing AI capabilities with traditional software development practices. Instead of relying on end-to-end AI systems that make all workflow decisions autonomously, ControlFlow allows as much or as little AI participation as needed, ensuring that developers **maintain visibility and control** over their applications.



Expand All @@ -40,6 +42,8 @@ ControlFlow prioritizes transparency and ease of debugging by providing native t
### 🤝 Seamless integration
ControlFlow is designed to integrate seamlessly with existing Python codebases, treating AI tasks as first-class citizens in the application logic. The `Task` class provides a clean interface for defining the inputs, outputs, and requirements of each task, making it easy to incorporate AI capabilities into traditional software workflows. This seamless integration allows for a gradual and controlled adoption of AI, reducing the risk and complexity of introducing AI into existing systems.

Together, these features make ControlFlow a powerful and flexible framework for building AI-powered applications that are transparent, maintainable, and aligned with software engineering best practices.


## Key concepts

Expand All @@ -52,12 +56,24 @@ Tasks represent discrete objectives for agents to solve. By specifing the expect
### 🤖 Agent
AI agents are assigned to tasks and responsible for completing them. Each agent is designed to be "single-serving," optimized only for completing its task in cooperation with other agents and the broader workflow.


## Why not "super-agents"?

Many agentic LLM frameworks rely on monolithic "super-agents": powerful, unconstrained models that are expected to achieve their goals by autonomously handling a wide range of tasks, tools, and behaviors. The resulting workflows are opaque, unpredictable, and difficult to debug.

This approach naively assumes that the technology is more advanced than it actually is. LLMs feel like magic because they can perform a wide variety of non-algorithmic tasks, but they are still fundamentally limited when it comes to generalizing beyond their traning data and techniques. Moreover, the failure modes of agentic LLMs are difficult to identify, let alone fix, making them difficult to trust in production environments or with mission-critical tasks.

In contrast to these "super-agent" approaches, ControlFlow promotes a modular, decoupled architecture where specialized agents are orchestrated to perform well-defined tasks, after which traditional software regains control of the application. This approach results in workflows that are more transparent, controllable, and debuggable, setting ControlFlow apart from other frameworks.


## Use cases
ControlFlow can be applied to a wide range of use cases, including:

- Building chatbots and conversational AI systems
- Automating content generation and summarization
- Developing AI-powered research and analysis tools
- Creating intelligent data processing pipelines
- Enhancing existing applications with AI capabilities
-
## Getting started

To get started with ControlFlow, install it using pip:
Expand Down

0 comments on commit c1369e5

Please sign in to comment.